когда функция будет включать вызов стека _Unwind_Resume в c ++? - PullRequest
3 голосов
/ 12 июля 2020

Сейчас я изучаю исключения 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 () , и мы видим callq 0x4008d0 _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.

однако, когда я пытаюсь имитировать этот прогресс с помощью вызова функция вызовет исключение, код ассемблера call <_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 Ответ

5 голосов
/ 12 июля 2020

Поскольку fn2 вызывает только fn, который объявлен как throw(), никакое исключение не может распространяться на активный кадр стека для fn. G CC распознает эту ситуацию и оптимизирует обработчик исключений.

В исходном случае это невозможно, потому что std::vector::at(size_type) может выбросить. Обработчик исключений необходим только из-за объявления throw(), чтобы вызвать std::unexpected() в случае исключения.

_Unwind_Resume отображается только в том случае, если для кадра стека требуется особый действие при раскручивании (например, вызов деструкторов или std::unexpected()). Без этого Itanium C ++ ABI (который используется G CC) вообще не требует каких-либо покадровых действий, поэтому эту реализацию иногда называют обработкой исключений с нулевой стоимостью .

...