2016-11-30 133 views
3

某處型recognision工作++代碼:如何時異常在C處理

try 
{ 
    foo(); 
} 
catch (const FooExceptionOne& e) 
{ 
    // ... 
} 
catch (const FooExceptionTwo& e) 
{ 
    // ... 
} 
catch (const std::exception& e) 
{ 
    // ... 
} 

FooExceptionOneFooExceptionTwostd::exception派生自定義類。

在引發異常的時刻;類型識別如何工作?它是一種動態投射還是多面體,發生在「引擎蓋下」?

我的第一個想法是動態鑄造,但(當然)它似乎非常緩慢的解決方案。

+2

不是答案,但應該由'const'引用捕獲異常。 –

+1

我實際上並不確定它是如何工作的,但是一個非常緩慢的解決方案在這裏不會成爲問題。例外情況不是爲了速度而設計的。 –

回答

5

GCC,鏘和Intel C++編譯器推型到寄存器中,作爲可以在此頁中可以看出:https://godbolt.org/g/w0lD0p

的代碼:

switch (throwType) { 
    case 0: 
    throw 0; 

    case 1: 
    throw 0.0; 

    case 2: 
    throw "test"; 
} 

被編譯爲以下彙編代碼中GCC:

.L17: 
    mov  edi, 4 
    call __cxa_allocate_exception 
    xor  edx, edx 
    mov  DWORD PTR [rax], 0 
    mov  esi, OFFSET FLAT:typeinfo for int 
    mov  rdi, rax 
    call __cxa_throw 
.L4: 
    mov  edi, 8 
    call __cxa_allocate_exception 
    xor  edx, edx 
    mov  QWORD PTR [rax], OFFSET FLAT:.LC1 
    mov  esi, OFFSET FLAT:typeinfo for char const* 
    mov  rdi, rax 
    call __cxa_throw 
.L3: 
    mov  edi, 8 
    call __cxa_allocate_exception 
    xor  edx, edx 
    mov  QWORD PTR [rax], 0x000000000 
    mov  esi, OFFSET FLAT:typeinfo for double 
    mov  rdi, rax 
    call __cxa_throw 

如從線可以看出:

mov  esi, OFFSET FLAT:typeinfo for int 
mov  esi, OFFSET FLAT:typeinfo for char const* 
mov  esi, OFFSET FLAT:typeinfo for double 

該類型的類型信息存儲在esi寄存器中的GCC中。然而,這是編譯器特有的,所以雖然GCC(以及Clang和Intel)的情況是這樣,但它可能不適用於任何其他編譯器(Borland等)。

throw使用的類型信息可以在編譯時完全確定,因此它不需要使用C++的RTTI特性,因爲它基本上是一個枚舉類型的ids,用於映射到相應的catch塊。

確定類型如何映射的規則可以在關於處理異常的標準的§15.3節中找到。