主函数执行时的C++堆栈溢出异常

Moh*_*ria 14 c++ stack-overflow

我有下面列出的代码,并在运行时报告堆栈溢出.我使用pass by value来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;
}
Run Code Online (Sandbox Code Playgroud)

n. *_* m. 26

这里明显发生的是延迟堆栈弹出.

在C和C++中,常见的调用约定是调用者从堆栈中弹出参数.作为一种常见的优化,许多编译器在每次调用后不会弹出参数,但是在多次调用之后执行此操作并将所有累积的参数一起弹出.这节省了一些指令,代价是可能溢出的更大堆栈.

在MSVC中,当禁用优化时,编译器会事先为给定函数中所需的所有调用分配并检查堆栈.这就是程序在打印任何内容之前崩溃的原因.

查看相应的装配

一些最初的说明main

    mov      eax, 1200120       ; 00124ff8H
    call     __chkstk
    sub      rsp, rax
Run Code Online (Sandbox Code Playgroud)

这个数字正是在堆栈上拟合三个对象实例所需的数字.

启用优化后,编译器足够智能以重用堆栈,因此不会崩溃.

优化组装

    mov      eax, 400032          ; 00061aa0H
    call     __chkstk
    sub      rsp, rax
Run Code Online (Sandbox Code Playgroud)

足够单个实例.