【问题标题】:Creating an 2-dimensional array of a struct results in crash创建结构的二维数组会导致崩溃
【发布时间】:2013-09-26 05:30:37
【问题描述】:

我正在尝试生成struct 的二维数组,但这会导致程序无法启动。窗口冻结,程序在几秒钟后退出。知道为什么吗?

这是我尝试定义数组 cells 的文件。

#ifndef _FIELD_H_
    #define _FIELD_H_

class Field {
    public:
        static const int minX = -400;
        static const int maxX = 400;
        static const int minY = 0;
        static const int maxY = 400;

        Field();

    private:
        struct absCell {
            int material;
            float health;
        } cells[maxX - minX + 1][maxY - minY + 1];
};

#endif

删除这四行后,程序就可以运行了:

        struct absCell {
            int material;
            float health;
        } cells[maxX - minX + 1][maxY - minY + 1];

知道这是怎么发生的吗?任何帮助表示赞赏!

更新

好的,显然问题是这个数组变得相当大。也许你可以帮我优化一下。

Material 必须是介于 0 和 10 之间的整数。 Health 必须是介于 0 和 1 之间的浮点数,最多包含 2 个小数位。

如何限制这些变量的大小?

更新 2

Mark B 建议使用vectors,而 itwasntpete 建议使用指针、new 和 delete。区别在哪里,这两种方法的优缺点是什么?再次感谢!

【问题讨论】:

  • 这本身并没有错。问题可能出在其他地方,当您进行更改时它恰好出现。尝试创建一个SSCCE的问题:sscce.org
  • 我要去除尘我的老化和有点雾的水晶球在main() 中建议你有类似Field fld; 的东西(更糟糕的是,@987654330 的 array @. 如果是这样,请注意此结构定义了一个固定的堆栈绑定数组,该数组包含大约 800x400 个成员,或 320000 个 intfloat 值。假设每个是 4 个字节,那就是 256000 个字节,或大约 2.44 MB 每个 Field 对象 的堆栈空间。简而言之,我认为您很可能会耗尽您的堆栈。请告诉我们您在哪里使用 @ 987654333@,特别是Field 类型变量的定义位置和方式。
  • 我估计您的班级对于每个实例将需要大约 2.5 Gb 的内存。这不是一个不可能的大数目,但它是相当多的。您是否尝试过减小数组的大小?
  • stackoverflow 的好例子。
  • @LarsEbert 对 update2 的回答,向量更容易,指针对于新手来说非常困难,任何阅读本论坛的内容都会告诉你。

标签: c++ arrays struct


【解决方案1】:

您正在堆栈上分配 struct absCell 的 801 * 401 (=321201) 个元素。假设你有一台 32 位机器,它是 2569608 字节(~2.45 MB)。根据this,它正在炸毁你的堆栈。

将元素移动到堆中:

class Field {
public:
    static const int minX = -400;
    static const int maxX = 400;
    static const int minY = 0;
    static const int maxY = 400;

    Field() {
        cells = new absCell*[maxX - minX + 1];
        for(int i=0; i<maxX - minX + 1; i++)
            cells[i] = new absCell[maxY - minY + 1];
    }

    ~Field() {
        for(int i=0; i<maxX - minX + 1; i++)
            delete[] cells[i];

        delete[] cells;
    }

private:
    struct absCell {
        unsigned char material;
        unsigned char health;
    }**cells;
};

更新

材料和健康可以保存在char中。访问健康你必须重新计算它:

put -> x*100
get -> x/100

更新 2

除非您有某些原因,否则使用向量很可能是更好的选择,正如 Mark B 的 answer 所描述的那样。

【讨论】:

  • 与 Mark B 建议的使用 vectors 相比,是否有任何(不利)优势?
  • @Lars Ebert 如果曾经复制过 Field,此版本可能会导致双重删除/未定义版本。
【解决方案2】:

基于更新说明:

您可以做的第一件事是通过为每个属性使用unsigned char 来轻松优化结构空间,对现有浮点数使用定点表示(例如,0.23 将存储为整数 23)。

然后用向量而不是数组将结构存储在堆上:

    struct absCell {
        unsigned char material;
        unsigned char health;
    };
    std::vector<std::vector<absCell> > cells_;

然后设置构造函数:

Field() : cells_(maxX - minX + 1, std::vector<absCell>(maxY - minY + 1)) {}

【讨论】:

    【解决方案3】:

    我的猜测是你达到了堆栈限制。当您制作该数组时,它试图将 801*401*8 字节放在您的堆栈上。我做了一个快速编译并且一直崩溃,直到我降低了你的各种最小值和最大值的数字。

    【讨论】:

      【解决方案4】:

      如果我的 sn-p 方法正确,那么您正在尝试创建一个数组。阵列的分配是基于堆栈的,需要超过 2 Mb 的大小。您的堆栈可能有少于 2Mb 的可用空间,因此代码会在您进入函数时立即崩溃。

      尝试动态分配相同的数组。

      【讨论】:

      • 非常感谢。我更新了我的问题。你知道如何优化struct吗?
      猜你喜欢
      • 2018-06-21
      • 1970-01-01
      • 2016-07-28
      • 1970-01-01
      • 1970-01-01
      • 2013-05-13
      • 2017-03-17
      • 1970-01-01
      相关资源
      最近更新 更多