6

我正在阅读Bjarne Stroustrup的 The Design and Evolution of C++。关于异常处理和异步信号,如下所述:

异常可以用来处理信号之类的事情吗?几乎可以肯定,在大多数 C 环境中都不会。问题是 C 使用了像 malloc 这样不可重入的函数。如果在 malloc 中间发生中断并导致异常,则无法阻止异常处理程序再次执行 malloc。

一个 C++ 实现,其中调用序列和整个运行时库是围绕重入的要求设计的,这将使信号有可能抛出异常

作者所说的“没有办法阻止异常处理程序再次执行malloc”是什么意思?使函数可重入如何使从信号处理程序中抛出异常成为可能?

4

3 回答 3

6

在我看来,这部分对于当前的 C++ 并没有多大意义。

在 C++ 中,没有办法将异常用作信号,因为信号意味着执行处理程序,然后(可能)继续执行。

但是,C++ 异常不能以这种方式工作。一旦您到达异常处理程序,堆栈已经回滚,并且在处理后无法“继续”:在 throw 之后(或在发生异常的函数调用之后)无法到达语句抛出)。

信号是异步的,但不是破坏性的,并且在可能发出信号后继续(即使当然必须注意信号处理程序中所做的事情),异常反而会破坏程序流并且不可能继续。

我想说这两个想法在逻辑层面上是不兼容的,图书馆是否可重入并不重要。

可能在早期的 C++ 设计中,有一个异常的恢复选项......

于 2011-06-30T14:41:29.573 回答
3

例如,如果对 malloc 的调用引发了一个信号,那么如果您从该信号处理程序中抛出异常,则异常抛出逻辑可以再次调用 malloc。由于 malloc 不是可重入的,因此您最终会遇到未定义的行为。

处理信号的一种方法是将信号事件推入事件队列并立即从信号处理程序返回。然后,当事件循环处理信号事件时,它可以做任何想做的事情,因为它不在信号处理程序的受限上下文中。

于 2011-06-30T14:04:23.790 回答
1

如果一个函数可以在执行过程中被中断并在被中断的调用完成之前再次调用,那么它就是“可重入的”。另一种看待它的方式:可以从信号处理程序中调用可重入函数。从信号处理程序中调用不可重入函数的所有赌注都没有了。应该从信号处理程序内部调用的唯一函数是那些已知可重入的函数。

malloc 不可重入。如果 malloc 发生 kaboom,则无法判断它是否在更新 malloc 在幕后使用的任何全局数据以跟踪分配的数据的过程中发生了 kaboom。

信号处理程序与异常的另一个问题:在信号处理程序中执行的代码本质上是在与主代码不同的线程中运行。如果可以处理信号,则信号处理程序的返回将返回到信号发出点之后。您将如何在信号处理程序中引发异常?这样做,信号处理程序不再返回!这意味着其余的执行是在信号处理程序中有效地完成的。现在当另一个信号出现时会发生什么?这两个概念只是不混合。重入只是这里的冰山一角。

于 2011-06-30T14:18:44.400 回答