主函数执行时的 C++ 堆栈溢出异常
C++ stack overflow exception on main function execution
我有下面列出的代码,当我 运行 它报告堆栈溢出。
我使用按值传递给 showTest()
。
我期望的是它将 Test
结构复制到堆栈(压入堆栈),然后在函数调用结束时 Test
结构将被释放(弹出堆栈)。
所以我打了三次电话。它应该推入堆栈并在每个函数调用结束时弹出。
如果它在每次调用函数时推入和弹出堆栈,我没有看到任何堆栈问题。
但是,我运行这段代码的时候,在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;
}
这里显然发生的是延迟堆栈弹出。
在 C 和 C++ 中,常见的调用约定是调用者从堆栈中弹出参数。作为一个常见的优化,许多编译器不会在 each 调用后弹出参数,而是在多次调用后弹出参数并将所有累积的参数一起弹出。这节省了一些指令,但代价是可能溢出的更大堆栈。
在 MSVC 中,当优化被禁用时,编译器会预先分配并检查堆栈以查找所有它需要的调用给定的功能。这就是程序甚至在打印任何内容之前就崩溃的原因。
main
中的一些第一个指令是
mov eax, 1200120 ; 00124ff8H
call __chkstk
sub rsp, rax
这个数字正是在堆栈上容纳对象的三个实例所需要的。
启用优化后,编译器足够智能,可以重用堆栈,因此不会发生崩溃。
mov eax, 400032 ; 00061aa0H
call __chkstk
sub rsp, rax
对于单个实例来说足够了。
我有下面列出的代码,当我 运行 它报告堆栈溢出。
我使用按值传递给 showTest()
。
我期望的是它将 Test
结构复制到堆栈(压入堆栈),然后在函数调用结束时 Test
结构将被释放(弹出堆栈)。
所以我打了三次电话。它应该推入堆栈并在每个函数调用结束时弹出。
如果它在每次调用函数时推入和弹出堆栈,我没有看到任何堆栈问题。
但是,我运行这段代码的时候,在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;
}
这里显然发生的是延迟堆栈弹出。
在 C 和 C++ 中,常见的调用约定是调用者从堆栈中弹出参数。作为一个常见的优化,许多编译器不会在 each 调用后弹出参数,而是在多次调用后弹出参数并将所有累积的参数一起弹出。这节省了一些指令,但代价是可能溢出的更大堆栈。
在 MSVC 中,当优化被禁用时,编译器会预先分配并检查堆栈以查找所有它需要的调用给定的功能。这就是程序甚至在打印任何内容之前就崩溃的原因。
main
中的一些第一个指令是
mov eax, 1200120 ; 00124ff8H
call __chkstk
sub rsp, rax
这个数字正是在堆栈上容纳对象的三个实例所需要的。
启用优化后,编译器足够智能,可以重用堆栈,因此不会发生崩溃。
mov eax, 400032 ; 00061aa0H
call __chkstk
sub rsp, rax
对于单个实例来说足够了。