提问者:小点点

函数在C++中什么时候会包含stack_unwind_resume调用?


我现在正在学习C++异常,遇到了一个麻烦,程序显示如下

#include<iostream>
#include<unistd.h>
#include<string>
#include<thread>
#include<vector>
#include<exception>
using namespace std;


vector<int> vec(20);


void fn()throw() {
        vec.at(10);
}

int main(){
        fn();

return 0;
}

我使用gdb来反汇编fn(),我们可以看到callq0x4008d0_unwind_resume@plt,这是一个对堆栈展开操作的调用,因为vector::at可能会抛出一个超出范围的异常

Dump of assembler code for function fn():
   0x00000000004009e6 <+0>:     push   %rbp
   0x00000000004009e7 <+1>:     mov    %rsp,%rbp
   0x00000000004009ea <+4>:     mov    $0xa,%esi
   0x00000000004009ef <+9>:     mov    $0x6020a0,%edi
   0x00000000004009f4 <+14>:    callq  0x400ba6 <std::vector<int, std::allocator<int> >::at(unsigned long)>
   0x00000000004009f9 <+19>:    jmp    0x400a11 <fn()+43>
   0x00000000004009fb <+21>:    cmp    $0xffffffffffffffff,%rdx
   0x00000000004009ff <+25>:    je     0x400a09 <fn()+35>
   0x0000000000400a01 <+27>:    mov    %rax,%rdi
   0x0000000000400a04 <+30>:    callq  0x4008d0 <_Unwind_Resume@plt>
   0x0000000000400a09 <+35>:    mov    %rax,%rdi
   0x0000000000400a0c <+38>:    callq  0x400880 <__cxa_call_unexpected@plt>
   0x0000000000400a11 <+43>:    pop    %rbp
   0x0000000000400a12 <+44>:    retq   
End of assembler dump.

但是,当我试图用调用函数将引发异常来模拟这个过程时,汇编代码调用<_unwind_resume>; 不存在,为什么?

#include<iostream>
#include<unistd.h>
#include<string>
#include<thread>
#include<vector>
#include<exception>
using namespace std;


class myException:public exception  
{  
        public:  
                myException(){ } 
};


void fn()throw() {
        throw myException();
}

void fn2()throw(){
        fn();
}


int main(){
        fn2();

        return 0;
}


函数fn2()的汇编代码,它不包括调用unwind_resume@plt,为什么?

(gdb) disassemble fn2
Dump of assembler code for function fn2():
   0x0000000000400aec <+0>:     push   %rbp
   0x0000000000400aed <+1>:     mov    %rsp,%rbp
   0x0000000000400af0 <+4>:     callq  0x400aa6 <fn()>
   0x0000000000400af5 <+9>:     nop
   0x0000000000400af6 <+10>:    pop    %rbp
   0x0000000000400af7 <+11>:    retq   
End of assembler dump.


共1个答案

匿名用户

由于fn2只调用fn(声明为throw()),因此没有异常可以传播到fn的活动堆栈帧。 GCC认识到了这种情况,并对异常处理程序进行了优化。

在原始情况下,这是不可能的,因为std::vector::at(size_type)可以抛出。 异常处理程序之所以需要是因为throw()声明,以便在发生异常时调用std::underments()

相关问题


MySQL Query : SELECT * FROM v9_ask_question WHERE 1=1 AND question regexp '(函数|c++|中|包含|stack_unwind_resume|调用)' ORDER BY qid DESC LIMIT 20
MySQL Error : Got error 'repetition-operator operand invalid' from regexp
MySQL Errno : 1139
Message : Got error 'repetition-operator operand invalid' from regexp
Need Help?