【发布时间】:2021-02-09 12:42:03
【问题描述】:
我正在阅读 C++ 中的异常支持,结果可能也适用于其他语言。
https://wiki.osdev.org/C%2B%2B_Exception_Support
http://www.ucw.cz/~hubicka/papers/abi/node25.html
发生了很多事情,我有点不知所措。我的问题是在展开过程中,C++ 是否需要内核的帮助(例如 setjmp/longjmp 如 cmets 中所述,这两个函数不涉及内核,但是我的问题仍然相同)?还是整个过程只发生在用户空间?
我可以理解本地线程的展开(想想 setjmp/longjmp),但无法理解远程线程是如何展开的。
如果所有的展开魔法都发生在用户空间,一个线程如何在没有内核帮助的情况下修改另一个错误线程以将其发送到处理代码?由于我相信线程上下文信息(任务结构)存在于内核中并且不允许直接从用户空间进行修改,而不访问线程上下文,它是如何实现的?谢谢!
更新:看起来我对任务结构有一些基本的误解。刚刚碰到一张关于信号处理的幻灯片 (signal handlers) (http://users.cms.caltech.edu/~donnie/cs124/lectures/CS124Lec15.pdf),在进入信号处理程序时,内核堆栈是空的,所有上下文信息都存在于用户堆栈中。我想可以使用信号与其他故障线程进行通信以放松?如果是这样,是否意味着 C++ 异常支持需要内核帮助,因为生成信号是内核调用?
更新:就问题而言,我对 Paul 的回答感到满意。我想根据我对评论/答案的阅读,从更广泛的意义上总结我对该主题的理解,如果我错了,请纠正我。
C++异常框架并没有指定具体的实现方式,下面总结就是我认为的“常见”。
异常对象有3个来源,产生的展开实现如下:
+------------------------------------------------+--------------------------------------------------------------------------+
| exception source | unwinding method |
+------------------------------------------------+--------------------------------------------------------------------------+
| a) exception created by `throw` | via code to walk the stack and assembly to transfer control to call site |
| b) exception created by hardware e.g. SIGFPE | via synchronous signal, and code to walk the stack |
| | and assembly to transfer control to call site |
| c)* exception created by remote process/thread | via asynchronous signal, and code to walk the stack |
| | and assembly to transfer control to call site |
+------------------------------------------------+--------------------------------------------------------------------------+
*对于案例 c),我不确定是否有任何实际使用需要由外部进程创建并在本地处理的异常,它不符合 throw/catch 语义要么(至少它是可行的),我把它放在这里只是为了完整性。
【问题讨论】:
-
我的问题是在展开过程中,C++ 是否需要内核的帮助 -- C++ 标准没有提及编译器如何实现异常处理,只提及异常处理是如何实现的应该表现得很好。
-
没有。最初它是作为一组宏实现的,它告诉您所有您需要了解的有关内核支持的信息。
setjmp()就足够了。 -
setjmp也不需要内核帮助。它可能会从中受益,但仅此而已。 -
@MSalters 我既没有声明也没有暗示
setjmp()需要内核支持。