c++ - 不抛出异常保证和堆栈溢出

标签 c++ exception exception-safety

有几个特殊函数通常保证不抛出异常,例如:

  • 析构函数
  • 交换方法

考虑以下 swap 实现,如 this answer 中所述:

friend void swap(dumb_array& first, dumb_array& second)
{
    using std::swap; 

    swap(first.mSize, second.mSize);  
    swap(first.mArray, second.mArray);  // What if stack overlow occurs here?
}

它使用两个 swap 函数 - 用于整数和指针。如果第二个函数会导致栈溢出怎么办?对象将被损坏。我猜它不是 std::exception,它是某种系统异常,比如 Win32-exception。但是现在我们不能保证不抛出,因为我们正在调用一个函数。

但所有权威来源都只是使用 swap 就好了,这里永远不会抛出异常。为什么?

最佳答案

一般来说,你无法处理堆栈耗尽的问题。该标准没有说明如果堆栈用完会发生什么,也没有说明堆栈是什么,有多少可用等等。操作系统可能会让您在构建可执行文件或运行时控制它,如果您正在编写库代码,所有这些都是无关紧要的,因为您无法控制进程有多少堆栈,或者在用户调用您的库之前已经使用了多少。

您可以假设堆栈溢出导致操作系统在您的程序之外执行某事。一个非常简单的操作系统可能会让它变得奇怪(未定义的行为),一个严肃的操作系统可能会把这个过程搞砸,或者如果你真的不走运,它会抛出一些实现定义的异常。我实际上不知道 Windows 是否为堆栈溢出提供了 SEH 异常,但如果提供了,那么最好不要启用它。

如果您不放心,可以将您的swap 函数标记为noexcept。然后在一致的实现中,任何试图离开函数的异常都会导致程序terminate()。也就是说,它以取出你的程序为代价来履行noexcept契约。

关于c++ - 不抛出异常保证和堆栈溢出,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/16080419/

相关文章:

java - 记录异常和Exception.printstacktrace之间的区别

java - Android 未处理的异常

c++ - 为什么 std::unique_ptr 没有明确要求 noexcept Deleter?

c++ - 分配器构造和销毁成员函数是否允许从内部逻辑抛出异常?

c++ - 如何使std::hex,std::bin,std::dec仅有效一次?

c++ - 在 C++ 中居中 Pascal 的三角形输出

c++ - 为什么结构在 Xcode 中不起作用,而在 Visual C++ 中起作用?需要帮助!

java - 即使有 NoSuchFileException ? Java(尝试在启动窗口上添加文件)

C++:为什么这个简单的 Scope Guard 有效?

c++ - 如何在 C++ 中删除 char *?