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