如何创建无限递归会抛出堆栈溢出异常?

时间:2013-03-16 03:02:38

标签: c++ exception stack stack-overflow callstack

我正在尝试使用以下程序创建堆栈溢出运行时异常:

void f(int a) {
  cout << a << ", ";
  f(++a);
}

int main () {
  f(0);
  return 0;
}

当我运行此程序时,我的计算机运行大约261824 call stack,然后发生command terminated运行时错误。现在我想知道:

  1. 这是堆栈溢出的一个很好的例子吗?如果是,为什么会发生command terminated错误?
  2. 我如何trycatch堆栈溢出异常?
  3. 我有很多空闲记忆;为什么我的堆栈不能占用我所有的记忆?
  4. 如何确定堆栈的大小与我的call stack
  5. 相对应

2 个答案:

答案 0 :(得分:6)

这些都是实施细节。从技术上讲,C ++实现不需要堆栈,只需要自动存储。至少有一个C实现在堆中使用了链接列表(好吧,根据我的理解,这是一个奇怪的系统),用于自动存储。

但是,通常,堆栈是内存地址空间的连续区域,该进程仅保留用于存储自动变量和调用帧的区域。它必须在其他任何事情发生之前保留,因为它必须是连续的,并且如果为了另一个目的分配了一些内存块,则堆栈将无法增长。

如果你想将整个内存地址空间用于堆栈,那么堆就没有空间(也就是免费商店)。所以堆栈不会使用所有内存......

1 MB是将堆栈设置为的传统值:很少有程序真正需要更多,甚至可以适度避免在堆栈上放入大量数据。在多线程环境中,每个线程最终都有自己的堆栈:因此保持较小也会使线程更便宜。现代系统可能将它设置得更大,因为它们为每个过程都有很多地址空间。

在64位系统上,为堆栈使用50位地址空间相对容易(比计算机当前处理的方式更多:谷歌数据中心处理数PB)。但是这样做的缺点是,只有在整个系统的虚拟内存被一个进程抓取后,你才会调试。这方面的好处并不是那么大。

堆栈的大小是实现定义的,并且不是由C ++标准公开的。请参阅编译器文档,了解如何确定其大小以及如何更改其大小。

C ++标准没有规定当你炸掉堆栈时会发生什么。通常,当堆栈被烧毁时,您可能会遇到严重问题:编写代码以使其不会发生,而不是在它发生后捕获它。

答案 1 :(得分:4)

  1. 是的,这是堆栈溢出。您获得的错误消息取决于平台 - 因此,如果您在其他类型的计算机上运行它,您可能会看到“堆栈溢出”。
  2. seen here没有好的可移植方式。这是因为你没有得到抛出的异常,你正在让操作系统以任何你想要的方式杀死你的进程。
  3. 您的堆栈限制远小于可用内存(堆栈通常为8-20MB)。在特定的操作系统设置中,如果您确实需要更大的值,则可以重新配置此值(Solaris上的ulimit -s 100000将其设置为100MB)。但通常达到堆栈限制意味着你做错了什么。小堆栈限制有助于操作系统具有虚拟内存分配方案,并且是堆栈溢出的早期错误捕获器(映像代码的较慢版本消耗所有可用内存超过一两个小时......对于其他任何运行都不那么有趣)。
  4. 这可能是依赖于操作系统或编译器的,并不是本身就融入C ++的东西。尝试this SO link有关确定堆栈大小的各种方法。