C++标准对堆栈溢出有何规定

What does the C++ standard say about stack overflow?

本文关键字:何规定 栈溢出 堆栈 标准 C++      更新时间:2023-10-16

我看了一下C++0x标准草案,据我所知,其中没有任何关于堆栈溢出的内容。搜索"堆栈溢出"没有结果,而搜索"堆栈"我只得到了堆栈展开和std::stack的引用。这是否意味着不可能有一个符合C++标准的实现,因为当内存被一个本地对象(如一个巨大的本地数组(耗尽时,不允许有任何机制来处理错误?

这个问题的答案表明,至少C标准没有提到堆栈溢出。

为了使问题具体化,请考虑这个程序

// Program A
int identity(int a) {
  if (a == 0)
    return 0;
  char hugeArray[1024 * 1024 * 1024]; // 1 GB
  return identity(a - 1) + 1;
}
int main() {
  return f(1024 * 1024 * 1024);
}

这个程序

// program B
int main() {
  return 1024 * 1024 * 1024;
}

我认为C++标准不允许任何C++实现在这两个程序上做明显不同的事情。事实上,程序A不会在任何现代机器上运行,因为它在堆栈上分配了一个EB的内存(想象一下这个函数实际上使用了这个巨大的数组,这样编译器就不能默默地删除它而不会产生不良影响(。C++标准允许程序A失败吗?

编辑:问题不在于标准是否应该定义堆栈溢出时发生的情况,而在于它说了什么

我不确定这是否是您想要的,但在C++03 ISO标准的附录B中有以下注意事项:

  1. 由于计算机是有限的,C++实现不可避免地会受到程序大小的限制可以成功处理。每次实施都应记录已知的限制。本文档可能会引用存在的固定极限,说明如何将可变极限计算为可用资源,或者说固定限制不存在或未知
  2. 这些限制可能会限制数量,包括以下描述的数量或其他数量

(我强调的是(我认为这意味着编译器允许其中一个函数工作,而另一个函数失败,这是完全合法的,前提是编译器说明了存在哪些限制,以及如何根据系统可用的资源计算这些限制。

行为未定义,因为标准没有定义超出资源限制的程序会发生什么。请注意,规范的附件B中有建议的限值。尽管该附件是非规范性的,实施过程可以忽略该附件,包括与其中规定的限值不同。在1.4[介绍合规性]中,规范中说

如果某个程序不违反本国际标准的规定,则合格实施应在其资源限制范围内接受并正确执行该程序。

没有任何内容说明一个不违反is规则但无法在实施的资源限制内接受和正确执行的程序会发生什么。因此,在这种情况下行为是不明确的。

堆栈溢出正在破坏操作系统现有的保护机制。这不是该语言的一个功能,因为所有机器可执行代码都有相同的保护。

如果您想捕捉这个特定的错误,您需要编写特定于操作系统的代码。例如,在Linux上,您需要捕获SIGSEGV(分段错误(信号。但是,请注意,这也可能是由于NULL指针的尊重或任何其他内存保护问题引起的,而不仅仅是堆栈溢出。

不确定是否使用Windows、OSX或移动设备。

堆栈溢出时发生的情况极其依赖于系统(CPU和操作系统,有时还依赖于编译器,因为它由编译器插入堆栈探测和其他安全扩展堆栈的机制(,因此不可能强制执行特定的响应;如果目标平台允许,最好的办法是建议更好的回应。大多数人不这样做;虽然有一种合理的方法来处理堆溢出,但当堆栈处于不一致状态时,可能会调用堆栈溢出处理程序(a(,其中有一个部分构建的堆栈帧,并且(b(可能涉及调用处理程序。。。这需要用于中断帧的堆栈空间。POSIX指定了一个sigaltstack()机制,但它也有限制,并且ANSI C/C++不能合理地依赖于POSIX的遵从性。