如果是类的成员,C ++数组会导致崩溃

时间:2017-08-20 14:14:17

标签: c++ arrays stack-overflow

我目前正在使用未使用STL容器构建的特定库。在将一些函数重构为类时,我遇到了基于以下模式的堆栈溢出。

class Base
{
    float values[1920 * 1080]; // causes overflow
public:
    Base() {}
};

int main()
{
    float values[1920 * 1080]; // does not
    Base t;
}

我知道你可以为Base::values分配动态内存,但是为什么它不会导致main中的堆栈溢出,但是在Base中,为什么堆栈空间看起来要小得多Base?也许这是显而易见的,我只是缺席了。

(上面使用Visual Studio 2017编译的示例,默认标志)

2 个答案:

答案 0 :(得分:0)

1920 * 1080 * sizeof(float)足以吹掉堆栈。 (8 Mb)

确保编译器不通过设置元素来删除值数组。

更改基数如下。

class Base {
    float * values;
    Base() {
         values = new float[1920*1080];
    }
    ~Base(){
         delete [] values;
    }
 }

还修复了复制和赋值运算符。

答案 1 :(得分:0)

如果你这样做:

float values[1920 * 1080];

您正在将浮点数组分配到堆栈中。

浮点数占用4个字节(32位),因此大小为[1920 * 1080]的浮点数组将占用,1920 * 1080 * 4 = 8,294,000个字节。

堆栈中包含太多字节,因此我们得到堆栈溢出,程序崩溃。

但是,如果你这样做:

float* values = new float[1920 * 1080];

您正在将float数组分配到堆上,这称为动态数组。

堆比堆栈大得多,只受可用内存的限制,并且总能容纳8,294,000个字节。因此,你不会在这样做时发生堆栈溢出。

当你访问动态数组的一个元素时,它会从内存加载到堆栈中,它不需要加载所有元素,只需要加载你需要的元素,这样你就不会在访问数组元素时获得堆栈溢出。缺点是访问每个变量所花费的时间更长(仍然只有大约50到150纳秒),并且当使用{{1}不再需要数组时,需要显式释放分配给动态数组的内存运算符或者你会得到内存泄漏。