DannyX DannyX - 5 days ago 4
C++ Question

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.

Answer

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.

Comments