为什么堆栈溢出在visualc++;? 在微软Visual C++ 2010中,我创建了一个程序,它可以导致堆栈溢出。当我使用“开始调试”运行程序时,当堆栈溢出发生时会抛出一个错误。当我以“启动而不调试”的方式运行它时,不会抛出任何错误,程序只是无声地终止,就好像它已成功完成一样。有人能给我解释一下发生了什么事吗?还有其他编译器没有在堆栈溢出时抛出错误吗

为什么堆栈溢出在visualc++;? 在微软Visual C++ 2010中,我创建了一个程序,它可以导致堆栈溢出。当我使用“开始调试”运行程序时,当堆栈溢出发生时会抛出一个错误。当我以“启动而不调试”的方式运行它时,不会抛出任何错误,程序只是无声地终止,就好像它已成功完成一样。有人能给我解释一下发生了什么事吗?还有其他编译器没有在堆栈溢出时抛出错误吗,c++,stack-overflow,C++,Stack Overflow,(我认为这是询问有关堆栈溢出问题的正确位置。)堆栈溢出是未定义的行为。编译器完全有权忽略它或导致任何事件发生。C++不会像托管环境那样牵手。堆栈溢出意味着未定义的行为。在调试模式下,您需要开销。您希望它检测是否损坏堆栈、缓冲区溢出等。此开销内置于调试工具和调试器中。在高级术语中,调试工具是额外的代码和数据,用于帮助标记错误,调试器用于检测标记的错误并通知用户(当然,除了帮助您调试之外) 如果您运行的项目是在发布模式下编译的,或者没有附加调试程序,那么当程序死机时,没有人会听到程序的尖叫:)如果一

(我认为这是询问有关堆栈溢出问题的正确位置。)

堆栈溢出是未定义的行为。编译器完全有权忽略它或导致任何事件发生。

C++不会像托管环境那样牵手。堆栈溢出意味着未定义的行为。

在调试模式下,您需要开销。您希望它检测是否损坏堆栈、缓冲区溢出等。此开销内置于调试工具和调试器中。在高级术语中,调试工具是额外的代码和数据,用于帮助标记错误,调试器用于检测标记的错误并通知用户(当然,除了帮助您调试之外)

如果您运行的项目是在发布模式下编译的,或者没有附加调试程序,那么当程序死机时,没有人会听到程序的尖叫:)如果一棵树倒在森林中


根据你的程序,C++是没有训练轮的编程。如果你撞到了墙,没有人会告诉你你搞砸了。你只会撞车然后烧掉,甚至更糟,撞车然后继续在一个非常残废的状态下奔跑,而不知道有什么不对劲。因此,它可以非常快。没有额外的检查或安全措施来防止它以处理器的全速和潜力(当然,还有您在程序中编码了多少额外步骤)在程序中燃烧。

很可能是编译器优化了预期的堆栈溢出。考虑下面的伪代码示例:

void RecursiveMethod(int n)
{
    if (n % 1024 == 0)
        print n;

    // call recursively
    RecursiveMethod(n + 1);
} 
该方法将递归地调用自身,并很快使堆栈溢出,因为没有退出条件

然而,大多数编译器使用一种将递归函数调用转换为循环构造的技术

应该注意的是,使用尾部递归,上述程序将在无休止的循环中运行,而不是静默退出

Bart de Smet有一篇很好的博客文章,解释了这种技术在.NET中的工作原理:


在调试版本中,会进行大量堆栈检查,以帮助您检测诸如堆栈溢出、堆栈损坏等问题。这些问题不会出现在发布版本中,因为它们会影响应用程序的性能。正如其他人指出的,堆栈溢出是未定义的行为,因此编译器根本不需要实现此类堆栈检查

当您处于调试环境中时,运行时检查将帮助您检测在发布版本中也会出现的问题,因此,如果您修复了在调试版本中检测到的所有问题,那么它们也应该在发布版本中修复。理论上。实际上,有时在调试版本中看到的bug在发布版本中并不存在,反之亦然


堆栈溢出不应该发生。通常,堆栈溢出只有在无意的递归函数调用或在堆栈上分配足够大的缓冲区时才会发生。前者显然是一个bug,后者应该使用堆来代替。

因为当进程堆栈溢出时,它不再是有效的进程显示错误消息需要堆栈。

至于为什么调试器能够抛出这样的异常,在这种情况下,进程被保留,因为它在调试模式下连接到调试器的进程。您的进程没有显示错误,调试器正在显示错误


在Windows计算机上,您可以捕获对应于堆栈溢出的SEH异常。例如,您可以看到boost::regex的源代码(Google For boost\u regex\u有\u MS\u STACK\u GUARD)。

谢谢。但是,如何在VisualC++中捕获堆栈溢出事件(或者如果可能的话)?@ QAZ:你不是。在Visual C++ 2010中,可以从Windows捕获结构化异常(SEH),其中包括访问违规、堆栈溢出等。然而,语言不是设计或意图捕捉这些事件的,VisualC++是最有可能设计的,以捕捉此类事件,这就是为什么它具有语言扩展和编译器支持(代码> >代码> >除了< /代码>)Visual C++是。C++本身不是.@ qAZ,你应该编写代码,它不会首先导致堆栈溢出。@ qas:没有任何方法来处理C和C++中的堆栈溢出,有或没有SEH。即使在堆栈溢出时捕捉到抛出的SEH异常(或者使用任何其他特定于平台的机制来检测SO),此时您的程序基本上已经完全崩溃了。试图继续做任何事情都可以释放你的鼻涕恶魔。@懒虫:除非你的系统在你实际上溢出了堆栈之前抛出了堆栈溢出通知——在这种情况下你可以抛出一个C++异常来正确地解压堆栈。这是对堆栈溢出的检测,尽管这是特定于平台的。有关示例,请参阅boost::regex的源代码。@qaz:re:您感到惊讶的是,很难检测/处理溢出:这是因为实际上很少有程序需要这种堆栈深度。体系结构在设计时很少考虑到这种超出范围的恢复/范围界定/大小调整,因为范围通常比任何人使用的都大几个数量级,因此如果你真的达到了这个程度,你就会陷入真正的困境。FWIW,树遍历有时可以在单个