# C++ Exceptions Support

By default, exception catching is disabled in Emscripten. For example, if you compile the following program:

    #include <stdio.h>

    int main() {
      try {
        puts("throw...");
        throw 1;
        puts("(never reached)");
      } catch(...) {
        puts("catch!");
      }
      return 0;
    }

The first `throw` will abort the program and you’ll see something like this in the output:

    throw...
    Aborted(Assertion failed: Exception thrown, but exception catching is not enabled. Compile with -sNO_DISABLE_EXCEPTION_CATCHING or -sEXCEPTION_CATCHING_ALLOWED=[..] to catch.)

If you want to opt-in, you have two following options.

## Emscripten (JavaScript-based) Exception Support

First, you can enable exceptions via Emscripten’s JavaScript-based support. To enable it, pass `-fexceptions` at both compile time and link time.

When you rebuild the example above with this flag, the output will change to:

    throw...
    catch!

Note that this option has relatively high overhead, but it will work on all JavaScript engines with WebAssembly support. You can reduce the overhead by specifying a list of allowed functions in which exceptions are enabled, see the `EXCEPTION_CATCHING_ALLOWED` setting.

## WebAssembly Exception Handling-based Support

Alternatively, you can opt-in to the native WebAssembly exception handling proposal. To enable it, pass `-fwasm-exceptions` at both compile time and link time.

Rebuilding the example with this flag will result in the same output as with `-fexceptions` above:

    throw...
    catch!

This option leverages a new feature that brings built-in instructions for throwing and catching exceptions to WebAssembly. As a result, it can reduce code size and performance overhead compared to the JavaScript-based implementation. This option is currently supported in several major web browsers, but may not be supported in all WebAssembly engines yet.

## Debugging Exceptions

### Stack Traces

For native Wasm exceptions, when ASSERTIONS is enabled, uncaught exceptions will print stack traces for debugging. ASSERTIONS is enabled by default in -O0 and disabled in optimized builds (-O1 and above). You can enable it by passing `-sASSERTIONS` to the `emcc` command line in optimized builds as well. To display Wasm function names in stack traces, you also need –profiling-funcs (or -g or -gsource-map).

In JavaScript, you can also examine the stack traces using WebAssembly.Exception.prototype.stack property. For example:

    try {
      ... // some code that calls WebAssembly
    } catch (e) {
      // Do something with e.stack
      console.log(e.stack);
    }

Stack traces within Wasm code are not supported in JavaScript-based exceptions.

### Handling C++ Exceptions from JavaScript

You can also catch and examine the type and the message of C++ exceptions from JavaScript, in case they inherit from `std::exception` and thus have `what` method.

`getExceptionMessage` returns a list of two strings: `[type, message]`. the `message` is the result of calling `what` method in case the exception is a subclass of `std::exception`. Otherwise it will be just an empty string.

    var sp = stackSave();
    try {
      ... // some code that calls WebAssembly
    } catch (e) {
      stackRestore(sp);
      console.log(getExceptionMessage(e).toString());
    } finally {
      ...
    }

In case the thrown value is an integer 3, this will print `int,`, because the message part is empty. If the thrown value is an instance of `MyException` that is a subclass of `std::exception` and its `what` message is `My exception thrown`, this code will print `MyException,My exception thrown`.

`getExceptionMessage` is available when exceptions are used and either `-sASSERTIONS` or `-sEXCEPTION_STACK_TRACES` is set, which are by default true at `-O0`. At `-O1` or above, you can export it separately by `-sEXPORTED_RUNTIME_METHODS=getExceptionMessage,decrementExceptionRefcount`.

If the stack pointer has been moved due to stack allocations within the Wasm function before an exception is thrown, you can use `stackSave()` and `stackRestore()` to restore the stack pointer so that no stack memory is leaked.

Note

If you catch a Wasm exception and do not rethrow it, you need to free the storage associated with the exception in JS using `decrementExceptionRefcount` method because the exception catching code in Wasm does not have a chance to free it. See `test_getExceptionMessage` in `test/test_core.py` for an example usage.

## Using Exceptions and setjmp-longjmp Together

See Using Exceptions and setjmp-longjmp Together.

## Limitations regarding std::terminate()

> - Currently std::set_terminate is NOT supported when a thrown exception does not have a matching handler and unwinds all the stack up to the topmost caller and crashes the program, i.e., there is no `catch` that catches it and the callers are not marked as `noexcept`. This applies to both Emscripten-style and WebAssembly exceptions. That functionality requires two-phase exception handling, which neither supports. So the following program does NOT print `my set_terminate`:

>       #include <iostream>
>       #include <exception>

>       int main() {
>         std::set_terminate([] {
>           std::cerr << "my set_terminate" << std::endl;
>           std::abort();
>         });
>         throw 3;
>       }

> - When the exception handling encounters a termination condition, libc++abi spec says we call __cxa_begin_catch() to mark the exception as handled and then call std::terminate(). But currently Wasm EH does not support calling __cxa_begin_catch(). So the following program prints `exception_ptr is null`, where it is supposed to print `exception_ptr is NOT null`; note that the use of `noexcept` here means that the `throw 3` will turn into a termination condition.

>       #include <iostream>
>       #include <exception>

>       int main() noexcept {
>         std::set_terminate([] {
>           auto ptr = std::current_exception();
>           if (ptr)
>             std::cerr << "exception_ptr is NOT null" << std::endl;
>           else
>             std::cerr << "exception_ptr is null" << std::endl;
>           std::abort();
>         });
>         throw 3;
>       }

>   This can possibly be supported in the future.