This answer claims:
The exception object is destroyed when the last catch block that does not exit via a re-throw (i.e. a parameterless throw expression evaluation) completes.
However, this code prints asdf
:
#include <iostream>
#include <thread>
#include <stdexcept>
std::exception& get_err() {
try {
throw std::runtime_error("asdf");
} catch (std::exception& e) {
return e;
}
}
int main() {
std::thread t;
{
std::exception& err = get_err();
t = std::thread([&](){
std::this_thread::sleep_for(std::chrono::seconds(1));
// is this not a use-after-free error?
std::cout << err.what() << "\n";
});
}
t.join();
return 0;
}
Is this undefined behavior? Why can I use a reference to this exception object long after the "last catch block"?
Is the l-value reference to err
extending the lifetime of the object (into the thread's lambda)? What if the lifetime wasn't extended, would this still work?
I am on MSVC 2019 C++20, but would be interested in other compilers/standard as well.