Home > OS >  How to save an exception and throw it later
How to save an exception and throw it later

Time:04-07

Say I want to create an exception object, but throw it a bit later. My use case is that the exception is generated in a thread, but I need to actually throw it from my main thread (because there's nobody to catch it in the child thread)

using namespace std;

runtime_error *ex = nullptr;

thread myThread( [&ex]{
    if (something_went_wrong) {
        ex = new runtime_error("Something went wrong");
        return;
    }
} );

myThread.join();
if (ex != nullptr) {
    throw *ex;
}

For what it's worth, the compiler seems happy with this, but I can see that it's a resource leak at best. Is there a right way to do this?

CodePudding user response:

std::exception_ptr is the C facility to store exceptions. It can usually avoid an extra allocation.

std::exception_ptr ex = nullptr;

std::thread myThread( [&ex]{
    if (something_went_wrong) {
        ex = std::make_exception_ptr(std::runtime_error("Something went wrong"));
        return;
    }
} );

myThread.join();
if (ex != nullptr) {
    std::rethrow_exception(ex);
}

And since it can store any type of exception, you can store anything that could be thrown in the thread by wrapping the lambda like:

std::thread myThread( [&ex]{
    try {
        // do things
    } catch (...) {
        ex = std::current_exception();
    }
} );

Alternatively, you can use a std::optional<std::runtime_error>

std::optional<std::runtime_error> ex;

std::thread myThread( [&ex]{
    if (something_went_wrong) {
        ex.emplace("Something went wrong");
        return;
    }
} );

myThread.join();
if (ex) {
    throw *ex;
}

Which won't leak since you don't dynamically allocate

CodePudding user response:

Here is one solution I found, but I liked the unique_ptr solution better. Writing it here for completeness:

using namespace std;

runtime_error *ex = nullptr;

thread myThread( [&ex]{
    if (something_went_wrong) {
        ex = new runtime_error("Something went wrong");
        return;
    }
} );

myThread.join();
if (ex != nullptr) {
    runtime_error e2 = *ex;
    delete ex;
    throw e2;
}
  • Related