8

我在使用 Visual Studio 2010 编译的程序中出现堆栈溢出。我有一个宏,它在 do-while 块中使用分配在堆栈上的小字符数组 (8 KiB) 执行一些与字符串相关的工作。然后我有一个函数,我在同一范围内多次使用这个宏。现在我得到堆栈溢出。

我假设堆栈分配是 do-while 块的本地分配,因此当块结束时,数组将不复存在,因此不会影响函数的整体堆栈使用,但看来我错了。

使用调试器,我可以看到在输入函数时调用了 _chkstk() 。作为该函数的参数,堆栈大小略大于该函数中每次调用宏的所有 8 KiB 数组的总和(由于其他局部变量而略大)。

我用一个简单的例子重现了这个问题:

void func(void)
{
    {char a[500000];}
    {char b[500000];}
    {char c[500000];}
    {char d[500000];}
    {char e[500000];}
}

在简单的控制台应用程序中,从 main() 调用此函数将导致堆栈溢出。但是,删除除一个块语句之外的所有语句都可以正常运行。

我想知道这是否按预期工作?

如何计算函数所需的总堆栈大小?如何计算函数所需的堆栈大小?即使超出范围,堆栈上的数组仍然会影响函数的总堆栈大小?

为什么我得到堆栈溢出时

4

2 回答 2

2

我很确定标准没有准确定义这些变量需要多少堆栈空间(或者实际上它们存储在堆栈上)。编译器当然不需要不为这些局部变量中的每一个分配空间。实际重用也可能高度依赖于编译器的优化级别 - 因此,如果您使用不同级别的优化进行编译(或者如果您启用/禁用某些优化功能),它可能会做不同的事情。

在 C++ 中,对包含变量的块定义了对构造函数和析构函数的调用,因此如果要使用std::vector,则在块结束时释放内存(从堆中分配)。

总结:空间可以重复使用,但绝不保证。

于 2013-05-11T22:09:39.237 回答
0

我想这是特定于编译器的。同样适用于 GCC:数组在超出范围后从堆栈中删除(但当所有数组属于同一块时,它会引发段错误)。

于 2013-05-11T22:08:13.980 回答