DannyX
DannyX

Reputation: 405

How type recognision works when exception handling

Somewhere in c++ code:

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

FooExceptionOne and FooExceptionTwo are custom classes derived from std::exception.

In moment when exception is thrown; how does type recognition works? Is it some kind of dynamic casting or plymorphism, happening "under the hood"?

My first thought was dynamic-casting, but (of course) it seems very slow solution.

Upvotes: 3

Views: 212

Answers (2)

Sergei Nikulov
Sergei Nikulov

Reputation: 5110

Take a look on following articles C++ exception handling internals and Exception Handling in LLVM.

Compiler will generate array/table with exceptions typeinfo for try/catch to search.

Upvotes: 0

Tommy Andersen
Tommy Andersen

Reputation: 7220

GCC, Clang and the Intel C++ compiler pushes the type into a register, as can be seen on this page: https://godbolt.org/g/w0lD0p

The code:

switch (throwType) {
  case 0:
    throw 0;

  case 1:
    throw 0.0;

  case 2:
    throw "test";
}

Is compiled to the following assembly code in 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

As it can be seen from the lines:

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

The typeinfo for the type is in GCC stored in the esi register. However this is compiler specific, so while this is the case for GCC (as well as Clang and Intel) it might not be for any other compiler (Borland, etc.).

The type info used by throw can be completely determined at compile time, so this does not need to use the RTTI feature of C++, as it is basically an enumeration of type ids, that are used to map to the corresponding catch block.

The rules determining how types are mapped, can be found in the standard, section § 15.3, about handling exceptions.

Upvotes: 5

Related Questions