[英]C++ binary compatible dll POD class member initialization causes crash
[英]C++ array causes crash if member of class
我目前正在使用的不是使用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编译,默认标志)
1920 * 1080 * sizeof(float)足以炸毁堆栈。 (8 Mb)
确保编译器不会通过设置元素来删除values数组。
如下更改基础。
class Base {
float * values;
Base() {
values = new float[1920*1080];
}
~Base(){
delete [] values;
}
}
还要修复复制和赋值运算符。
如果您这样做:
float values[1920 * 1080];
您正在将float数组分配到堆栈上。
浮点数占用4个字节(32位),因此大小为[1920 * 1080]的浮点数数组将占据1920 * 1080 * 4 = 8,294,000字节。
太多的字节无法包含在堆栈中,因此我们会发生堆栈溢出,程序崩溃。
但是,如果您这样做:
float* values = new float[1920 * 1080];
您正在将float数组分配到堆上,这称为动态数组。
堆比堆栈大很多,仅受可用内存的限制,并且将始终能够容纳8,294,000字节。 因此,这样做不会导致堆栈溢出。
当您访问动态数组的一个元素时,它会从内存中加载到堆栈中,它不需要加载所有元素,只需加载所需的元素,因此在访问数组元素时也不会导致堆栈溢出。 缺点是访问每个变量所花费的时间更长(仍然只有大约50至150纳秒),并且当不再需要使用delete []
运算符来分配给动态数组的内存时,则需要显式释放分配给该数组的内存。否则会发生内存泄漏。
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.