Question: When an exception is thrown in `C++` and the stack is unwound, how is is the correct handler (`catch` clause) picked to handle the exception?

```
void f1()
{
    throw 1;
}

void f2()
{
    try
    {
        f1();
    }
    catch(const char* e)
    {
        std::cout << "exc1";
    }
}

...
try
{
    f2();
}
catch(int& e)
{
    std::cout << "exc2";
}
...

```

For example this code unsurprisingly prints `"exc2"` because `catch(int& e)` is capable of handling the `1` `int` typed object.

What I don't understand is, how can this be resolved statically? Or is it resolved dynamically? Is type information propagated with the exception?

Answer: 
As for most things, the C++ standard doesn't specify an implementation, but constrains valid implementations. There won't be a universal answer that knows about the specifics.

The Itanium ABI is a popular ABI that provides language-agnostic exception support. In that implementation, the unwinding API invokes the *personality function* of the stack frame, which receives the exception context, an exception structure and a reference to the exception handling table that guides catch behavior. The personality function is looked up based on the call's return address in the program's exception tables; it is assumed that the only instructions that can initiate an exception are call instructions. (GCC has extensions that allow to throw from signal handlers by enabling "non-call exceptions".) Compilers that use the Itanium ABI provide a personality function that knows how to check the runtime type of exception objects, and they compare that type to elements of the exception table.

There are other ways to do that. For instance, on 32-bit Windows, exception handling works by setting up handler functions, on the stack, as linked list items. These linked list nodes contain the address of exception handlers, and they use an [EXCEPTION\_RECORD](https://msdn.microsoft.com/en-us/library/windows/desktop/aa363082(v=vs.85).aspx) to figure out where to go from there. I'm a bit sparse on the details myself, unfortunately.

The Itanium ABI, by the way, is not exclusive to C++. For instance, on Apple platforms, Objective-C code uses the Itanium ABI for exceptions as well. This has the interesting property that a catch-all clause in either language will catch exceptions from the other language.
You could say that "the type information is propagated with the exception", but technically that's not true. When you `throw` something, that object gets copied/moved and the compiler will look for a [appropriate `catch` clause](http://en.cppreference.com/w/cpp/language/try_catch) in the order that they appear, where the object will get copied/moved to:

> 
> The exception is a match if any of the following is true:
> 
> 
> * E and T are the same type (ignoring top-level cv-qualifiers on T)
> * T is an lvalue-reference to (possibly cv-qualified) E
> * T is an unambiguous public base class of E
> * T is a reference to an unambiguous public base class of E
> * T is (possibly cv-qualified) U or const U& (since C++14), and U is a pointer or pointer to member (since C++17) type, and E is also a pointer or pointer to member (since C++17) type that is implicitly convertible to U by one or more of
> 
> 
> 	+ a standard pointer conversion other than one to a private, protected, or ambiguous base class
> 	+ a qualification conversion
> 	+ a function pointer conversion
> 	 (since C++17)
> 	+ T is a pointer or a pointer to member or a reference to a const pointer (since C++14), while E is `std::nullptr_t`.
> 
> 
> 

Additionally, if there is a catch-all clause (`catch (...)`), then it is taken if any of the above points do not apply. If no `catch` clause is suitable, the exception continues its way up the call stack.