程序返回-1073741571而不是永远进行的值

Program returns a value of -1073741571 instead of going forever

本文关键字:永远 返回 -1073741571 程序      更新时间:2023-10-16

我正在学习有关功能的学习,并决定制作一个循环,其中两个函数(在这种情况下为 funcAfuncB(永远互相呼叫,但在一段时间后停止执行。代码看起来像这样:

#include <iostream>
void funcA(); //forward declaration
//funcB calls funcA 
void funcB()
{
    funcA();
}
//funcA prints 1 and calls funcB again 
void funcA()
{
    std::cout<<1;
    funcB();
}
//main calls funcB
int main()
{
    funcB();
    return 0;
}  

返回的值是-1073741571(0xC00000FD(。您能透露为什么会发生这种情况吗?

好的,所以由于这是Windows 10上的GCC

未经任何优化启用了两个功能。

b():
        push    rbp
        mov     rbp, rsp
        call    foo()
        call    a()
        nop
        pop     rbp
        ret
a():
        push    rbp
        mov     rbp, rsp
        call    b()
        nop
        pop     rbp
        ret

其他答案指出,每个呼叫都在堆栈信息上留下,如何返回到称为函数的函数。现在,由于函数永远不会返回此信息,因此永远不会从堆栈中删除此信息,但会不断添加。结果,您有堆栈溢出,其中windows上的value 0xC00000FD表示。

现在,如果您启用优化(-O2(编译器可以弄清楚这是不定式的循环(使用称为尾部递归的技术(。

b():
        sub     rsp, 8
.L2:
        call    foo()
        jmp     .L2
a():
        sub     rsp, 8
.L6:
        call    foo()
        jmp     .L6

因此,通过启用了优化,您将在您期望的那样具有不定式的循环。

从理论上讲,这永远存在的问题是,每当函数称为函数时,都需要在称为'stack'的东西上保留一些内存。最终,该"堆栈"上没有更多的空间,您会得到一个stackoverflowException。0xC00000FD是Windows使用的错误代码来告诉您stackoverflowException发生了

每当您调用函数时,该程序都会保留少量空间以保留该功能的信息(本地变量的空间,有关在功能退出后返回何处的信息,等等。(。此内存是从称为呼叫堆栈的区域(或简称为"堆栈"(分配的,当功能完成运行时,它已返回到堆栈。

堆栈通常具有固定的小尺寸。如果您有很长的呼叫链(通常以数万个呼叫测量(,则可以用完堆栈空间,并且该程序将以称为堆栈溢出的错误终止。这就是您程序中正在发生的事情。

一般而言,如果您具有递归(或相互递归(功能,则需要确保递归深度不会"太大",以便某些"太大"或这种事情可能会发生。在某些特殊情况下,有些编译器可以认识到您正在编写递归代码,并将其转换为不分配多个堆栈框架的代码(有关更多详细信息,请参见"尾部淘汰"(,但这是例外,而不是例外规则。