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

时间:2018-07-09 05:13:58

标签: c++ stack-overflow

我有下面列出的代码,运行时它报告堆栈溢出。 我使用按值传递给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;
}

1 个答案:

答案 0 :(得分:26)

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

在C和C ++中,常见的调用约定是调用者从堆栈中弹出参数。作为一种常见的优化方法,许多编译器不会在 each 调用之后弹出参数,而是在多次调用之后弹出参数,并将所有累积的参数一起弹出。这样就节省了一些指令,但代价是可能会溢出较大的堆栈。

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

See corresponding assembly

main中的一些第一条指令是

    mov      eax, 1200120       ; 00124ff8H
    call     __chkstk
    sub      rsp, rax

这个数字恰好适合在堆栈中容纳对象的三个实例。

启用优化后,编译器足够聪明,可以重用堆栈,因此不会崩溃。

Optimised assembly

    mov      eax, 400032          ; 00061aa0H
    call     __chkstk
    sub      rsp, rax

足以容纳一个实例。