C++ C++;主函数执行时出现堆栈溢出异常
我有下面列出的代码,当我运行它时,它会报告堆栈溢出。 我使用通过值传递到C++ C++;主函数执行时出现堆栈溢出异常,c++,stack-overflow,C++,Stack Overflow,我有下面列出的代码,当我运行它时,它会报告堆栈溢出。 我使用通过值传递到showTest()。 我所期望的是,它将把Teststruct复制到堆栈中(推送到堆栈中),然后在函数调用结束时,将释放Teststruct(从堆栈中弹出)。 所以我打了三次电话。它应该推到堆栈上,并在每个函数调用结束时弹出 如果每次调用函数时它都会打开或弹出堆栈,我看不到任何堆栈问题。 但是,当我运行此代码时,它会在main的第一行报告堆栈溢出异常。(我使用Visual Studio 2017。) 如果我删除一个show
showTest()
。
我所期望的是,它将把Test
struct复制到堆栈中(推送到堆栈中),然后在函数调用结束时,将释放Test
struct(从堆栈中弹出)。
所以我打了三次电话。它应该推到堆栈上,并在每个函数调用结束时弹出
如果每次调用函数时它都会打开或弹出堆栈,我看不到任何堆栈问题。
但是,当我运行此代码时,它会在main
的第一行报告堆栈溢出异常。(我使用Visual Studio 2017。)
如果我删除一个showTest()
函数调用,那么我就可以让它工作
如有任何反馈,将不胜感激
#include <iostream>
struct Test
{
static int Userid;
int data[100000] = { };
Test()
{
++Userid;
};
};
int Test::Userid = 0;
void showTest(Test i_myint)
{
std::cout << "test" << std::endl;
}
int main()
{
Test *pint = new Test();
showTest(*pint);
Test *pint2 = new Test();
showTest(*pint2);
Test *pint3 = new Test();
showTest(*pint3);
return 0;
}
#包括
结构测试
{
静态int用户id;
int数据[100000]={};
测试()
{
++用户标识;
};
};
int Test::Userid=0;
无效显示测试(测试i_myint)
{
std::cout这里明显发生的是延迟堆栈弹出
在C和C++中,普通调用约定是调用方从堆栈中弹出参数。作为一种常见的优化,许多编译器在每次调用之后都不弹出参数,但是在多次调用之后,将所有累积的参数一起弹出,这样就节省了一些指令,但牺牲了一个可能溢出的较大的堆栈。
在MSVC中,当优化被禁用时,编译器会预先分配和检查堆栈,以获取给定函数中所需的所有调用。这就是为什么程序甚至在打印任何内容之前就崩溃的原因
main
中的一些前指令是
mov eax, 1200120 ; 00124ff8H
call __chkstk
sub rsp, rax
这个数字正好适合堆栈上对象的三个实例
启用优化后,编译器足够聪明,可以重用堆栈,因此不会发生崩溃
对于单个实例来说已经足够了。如果将数组大小减小到10k,会发生什么?您是使用64位还是32位体系结构?这些数组中的每一个都是~400k。Visual Studio的默认堆栈大小为~1mb。两次挤压,三次明显地冲击堆栈。那么,现在我们,显然是您,知道了,实际问题是什么?答案是什么是不这样做。@RetiredInja为什么不重用第一次调用的堆栈?谁知道呢?如果OP共享使用的编译器,我们可以查看汇编程序并找出答案。请注意,某些操作系统不支持堆栈上这么大的对象,因为它们只映射了一个或两个保护页,从而导致堆栈映射的扩展g访问时。跳过这些将获得未映射的内存。这是一个很好的捕获,尽管问题中的对象是临时对象,其生存期不会重叠。应该需要一个优化器来确定空间是否可以重用。可能这与可调试性有关。(作为旁注,该标准没有在[implimits]中规定最小堆栈大小,尽管存在256kiB的“最小-最大”对象大小,即262144字节。)n.m感谢您的回答。这是我正在寻找的答案。
mov eax, 400032 ; 00061aa0H
call __chkstk
sub rsp, rax