gpt4 book ai didi

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

转载 作者:IT老高 更新时间:2023-10-28 22:34:44 26 4
gpt4 key购买 nike

我有下面列出的代码,当我运行它时它会报告堆栈溢出。我使用传递值到 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 中,当优化被禁用时,编译器会预先分配并检查堆栈中的所有在给定函数中需要的调用。这就是程序在打印任何内容之前就崩溃的原因。

See corresponding assembly

main 中的一些第一条指令是

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

这个数字恰好是在堆栈中容纳三个对象实例所需的数字。

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

Optimised assembly

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

一个实例就足够了。

关于主函数执行时的 C++ 堆栈溢出异常,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/51238568/

26 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com