C ++标准对堆栈溢出有什么看法?

时间:2011-07-05 23:20:20

标签: c++ stack-overflow undefined-behavior

我看了一下C ++ 0x标准草案,据我所知,那里没有堆栈溢出。搜索“堆栈溢出”不会产生任何结果,并且搜索“堆栈”我只获得了堆栈展开和std :: stack的引用。这是否意味着没有符合C ++标准的实现,因为当本地对象(例如巨大的本地数组)耗尽内存时,没有允许处理错误的机制?

this question的答案表明至少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不会在任何现代机器上运行,因为它在堆栈上分配了一个exabyte内存(想象一下该函数实际上使用了巨大的数组,因此编译器无法以静默方式将其删除而不会产生不良影响)。 C ++标准是否允许程序A失败?

编辑:问题不在于标准应该定义堆栈溢出会发生什么,问题是它说什么,如果有的话。

4 个答案:

答案 0 :(得分:14)

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

  
      
  1. 因为计算机是有限的,所以C ++实现不可避免地受到程序大小的限制   可以成功处理。每个实施都应记录已知的限制。本文档可能引用存在的固定限制,说明如何计算变量限制作为函数   可用资源,或者说固定限制不存在或未知。
  2.   
  3. 限制可能会限制包含下述数据或其他数量的数量。
  4.   

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

答案 1 :(得分:4)

行为未定义,因为标准没有定义超出资源限制的程序会发生什么。请注意,规范的附录B中有建议的限制。该附件虽然是非规范性的,但实施可以忽略该附件,包括具有与那里规定的不同的限制。在1.4 [intro.compliance]中,规范说

  

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

没有任何内容表明,如果程序中没有违反IS中的规则但在实现的资源限制内无法接受和正确执行,那将会发生什么。因此,对于这种情况,行为是不确定的。

答案 2 :(得分:1)

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

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

不确定Windows,OSX或移动设备。

答案 3 :(得分:1)

堆栈溢出会发生什么情况与系统有关(CPU和OS,有时是编译器,因为编译器可以插入堆栈探测和其他机制来安全地扩展堆栈),所以不可能强制要求特定的响应;可以做的最好的事情是建议在目标平台允许的情况下优先的响应。大多数人没有;虽然有一种合理的方法来处理堆溢出,但是当堆栈处于不一致状态时,可能会调用堆栈溢出处理程序(a),其中包含部分构造的堆栈帧,并且(b)可能涉及调用处理程序...需要中断帧的堆栈空间。 POSIX指定了sigaltstack()机制,但它也有限制,ANSI C C / C ++不能合理地依赖于POSIX合规性。