到达放松处理程序
Reaching unwind handlers
>知道为什么代码看起来像这样吗
list<Foo> fooList;
processList(&fooList);
生成以下机器代码
lea rax, [rbp-48]
mov rdi, rax
call processList(std::__cxx11::list<Foo, std::allocator<Foo> >*)
lea rax, [rbp-48]
mov rdi, rax
call std::__cxx11::list<Foo, std::allocator<Foo> >::~list()
jmp .L11
mov rbx, rax
lea rax, [rbp-48]
mov rdi, rax
call std::__cxx11::list<Foo, std::allocator<Foo> >::~list()
mov rax, rbx
mov rdi, rax
call _Unwind_Resume
.L11:
add rsp, 40
pop rbx
pop rbp
ret
特别是,在无条件jmp .L11
之后,我没有看到任何通向该线的路径
(这是GCC 6.2,没有优化,在编译器资源管理器上生成(
为了进行比较,clang 5.0.0 产生
call processList(std::__cxx11::list<Foo, std::allocator<Foo> >*)
jmp .LBB5_1
.LBB5_1:
lea rdi, [rbp - 24]
call std::__cxx11::list<Foo, std::allocator<Foo> >::~list()
add rsp, 48
pop rbp
ret
lea rdi, [rbp - 24]
mov ecx, edx
mov qword ptr [rbp - 32], rax
mov dword ptr [rbp - 36], ecx
call std::__cxx11::list<Foo, std::allocator<Foo> >::~list()
mov rdi, qword ptr [rbp - 32]
call _Unwind_Resume
同样,有一个无条件跳转到返回块,以及似乎无法访问的平仓块(从第二个lea rdi
开始(。
在对C++异常机制进行一些研究后,我的结论是该过程如下:
- 在异常引发时,
__cxa_throw
被调用。这有点像longjmp()
函数被调用但永远不会返回。该函数执行两个主要任务- 它在调用堆栈中向上走来寻找捕获。如果找不到,
std::terminate
就会被调用。 - 如果它确实找到了一个 catch 块,那么它会调用当前函数和 catch 块之间的所有展开处理程序,然后调用 catch 块。
- 它在调用堆栈中向上走来寻找捕获。如果找不到,
回到我的原始机器代码(在编译器资源管理器中关闭过滤(。哈希之后的评论。
# this is the normative path
call std::list<Handle, std::allocator<Handle> >::~list()
# unconditional jump around the unwind handler
jmp .L11
.L10:
# unwind handler code, calls the local variable destructor
mov rbx, rax
.loc 2 30 0
lea rax, [rbp-32]
mov rdi, rax
call std::list<Handle, std::allocator<Foo> >::~list()
mov rax, rbx
mov rdi, rax
.LEHB1:
# carry on unwinding
call _Unwind_Resume
.L11:
然后是异常表
.section .gcc_except_table,"a",@progbits
.LLSDA1386:
.byte 0xff
.byte 0xff
.byte 0x1
.uleb128 .LLSDACSE1386-.LLSDACSB1386
.LLSDACSB1386:
# entry for unwind handler
.uleb128 .LEHB0-.LFB1386
.uleb128 .LEHE0-.LEHB0
.uleb128 .L10-.LFB1386
.uleb128 0
.uleb128 .LEHB1-.LFB1386
.uleb128 .LEHE1-.LEHB1
.uleb128 0
.uleb128 0
我猜 unwind 处理程序函数可以根据堆栈上的地址和此表中的偏移量计算出展开处理程序块的位置。
相关文章:
- 获取日期异步信号安全吗?如果在信号处理程序中使用,它会导致死锁吗
- 如何在信号处理程序和普通函数中对全局变量进行互斥读写操作
- 为什么我的 IExtractIcon 处理程序没有被调用?
- 在遍历处理程序的向量时注册和注销处理程序
- 有可能在信号处理程序中设置promise吗
- 在信号处理程序中捕获C++未处理的异常并恢复应用程序
- 通过安装信号处理程序关闭多线程应用程序
- QDateTime::toString() 在退出处理程序中使用时失败
- 如何在 WindowProc 处理程序中区分箭头键和数字键盘?
- async_write完成处理程序最早何时完成?
- C++事件系统 - 多态事件和事件处理程序
- 具有shared_ptr的处理程序中的分段错误
- 为什么我的信号处理程序只执行一次?
- GTK C++:找不到信号处理程序 您是否使用 -rdynamic 进行了编译?
- 如何使用从处理程序调度的最终回调将响应异步返回给调用方on_read?
- C++ 在信号处理程序后继续执行
- wxWidgets 拖放文件事件处理程序初始化问题(无效static_cast)
- 某些 boost::asio 异步函数是否将处理程序连接到操作,以便处理程序被触发一次?
- 没有信号处理程序的POSIX定时器的目的是什么?
- 处理程序的模块列表中有一个错误的模块"WebSocketModule"