我正在阅读Bjarne Stroustrup撰写的 C ++的设计和演变。关于异常处理和异步信号,如下所述:
可以使用异常来处理信号之类的事情吗?几乎肯定不会在大多数C环境中。问题是C使用不可重入的malloc等函数。如果在malloc中间发生中断并导致异常,则无法阻止异常处理程序再次执行malloc。
一个C ++实现,其中调用序列和整个运行时库是围绕重入的要求而设计的,这样可以使信号抛出异常
作者的意思是什么“没有办法阻止异常处理程序再次执行malloc”?如何使函数重入使得从信号处理程序中抛出异常成为可能?
答案 0 :(得分:4)
在我看来,对于当前的C ++来说,这部分并没有多大意义。
在C ++中,没有办法将异常用作信号,因为信号意味着执行处理程序然后(可能)继续执行。
然而,C ++异常不起作用。一旦你到达异常处理程序,堆栈就已经回滚了,并且在处理之后无法“继续”:没有办法在抛出之后到达语句(或者在函数调用之后获取异常抛出)。
信号是异步的但不是破坏性的并且在信号可能之后继续(即使当然必须关注信号处理程序中的操作),异常反而破坏程序流并且继续是不可能的。
我认为这两个想法在逻辑层面上是不兼容的,如果图书馆是可重入的,那么这并不重要。
可能在早期的C ++设计中有一个例外的简历选项......
答案 1 :(得分:3)
例如,如果对malloc的调用引发了一个信号,那么如果你从该信号处理程序中抛出一个异常,则异常抛出逻辑可以再次调用malloc。由于malloc不是可重入的,因此你会遇到未定义的行为。
处理信号的一种方法是将信号事件推入事件队列并立即从信号处理程序返回。然后,当事件循环处理信号事件时,它可以做任何想做的事情,因为它不在信号处理程序的受限上下文中。
答案 2 :(得分:1)
如果一个函数在执行过程中被中断并且在该中断调用完成之前再次被调用,则该函数是“可重入的”。查看它的另一种方法:可以从信号处理程序中调用可重入函数。从信号处理程序中调用非重入函数时,所有投注均已关闭。应该从信号处理程序内部调用的唯一函数是那些已知可重入的函数。
malloc不可重入。如果malloc进入kaboom,则无法告知kaboom是否在更新任何全局数据malloc后台使用kaboom来跟踪分配的数据。
信号处理程序与异常的另一个问题:在信号处理程序中执行的代码本质上是在与主代码不同的线程中运行。 如果信号可以被寻址,则信号处理程序的返回返回到信号被引发的点之后。你如何在信号处理程序中抛出异常?这样做,信号处理程序不再返回!这意味着执行的其余部分是在信号处理程序内有效完成的。现在发生另一个信号时会发生什么?这两个概念不混合。重入只是冰山一角。