Recursive main()-为什么会出现故障?
为什么以下程序出现故障Recursive main()-为什么会出现故障?,c,segmentation-fault,stack-overflow,C,Segmentation Fault,Stack Overflow,为什么以下程序出现故障 int main() { main(); } 尽管它是一个没有结束的递归,因此从定义上来说是无效的,但我不明白为什么它会出现故障(gcc 4.4.3和clang 1.5(trunk))。因为它每次调用自己时都会分配一点堆栈空间;最终,它会耗尽堆栈空间并将故障隔离。不过,我有点惊讶它会出现一个segfault;我早就料到了(鼓声) 您会得到一个(!)它会导致堆栈溢出,并在您的系统上被诊断为segfault。它在没有基本情况的情况下递归,从而导致堆栈溢出 int main(
int main() { main(); }
尽管它是一个没有结束的递归,因此从定义上来说是无效的,但我不明白为什么它会出现故障(gcc 4.4.3和clang 1.5(trunk))。因为它每次调用自己时都会分配一点堆栈空间;最终,它会耗尽堆栈空间并将故障隔离。不过,我有点惊讶它会出现一个segfault;我早就料到了(鼓声) 您会得到一个(!)它会导致堆栈溢出,并在您的系统上被诊断为segfault。它在没有基本情况的情况下递归,从而导致堆栈溢出
int main() { main(); }
将导致堆栈溢出
但是,
如下所示的优化版本(非调试模式):
int main() {
return main();
}
将在尾部递归调用中转换递归,也称为无限循环 每个函数调用都会在堆栈中添加entires,当函数退出时,这些条目将从堆栈中删除。
这里我们有递归函数调用,它没有退出条件。因此,一个接一个的函数调用数量是无限的,这个函数永远不会退出,也永远不会从堆栈中删除实体,这将导致堆栈溢出。它被称为
堆栈溢出@wic:据我们所知,它不是一个植物,而是一个真正的问题。非常有趣@T.J:是的,OP是一个天才,甚至连它自己都不知道:)我会担心没有让程序崩溃和烧坏的编译器。应该有一个徽章,可以在不知道答案是堆栈溢出的情况下提问。这台机器有4GB的RAM,它在不到一秒钟的时间内就可以检测出故障。我不认为它的内存用完了。您的意思是堆栈只能很小,以至于发生的速度很快吗?@user2999831堆栈通常限制在1兆字节左右。@user299831:它与您的系统中有多少RAM无关。对于每个线程,都有最大堆栈大小(VisualStudio上为1MB,可以更改)。如果超过该大小,则会出现堆栈溢出。@user299831:stack!=RAM,堆栈空间是在程序开始时预先分配的,并且通常是有限的(我甚至不确定您是否能得到上面提到的1MB sharptooth,但我的C编程在这一点上已经过时了)。此外,今天的机器速度非常快,您的程序除了递归的main
调用之外什么都不做,它可以非常快地完成,因为它只需要增加(减少?)寄存器并执行跳转。ulimit-s
返回的值以kB为单位,因此8192表示8MB。实际上,对于这个示例,gcc-O3也会优化循环。@尼克,这两个循环有什么不同?@Adil,它依赖于编译器,但如果我们不显式地“返回”主循环,编译器可能不会将其转换为尾部递归。(示例案例:if(1){main();}返回0;
和if(1){return main();}返回0;
)令人惊讶的是,当我第一次单击该链接时,我立即发现堆栈溢出!不是很深的一堆,我想。。。