I am trying to get reference to std::exception
which is held by std::exception_ptr
.
Here's what I have tried:
#include <iostream>
using namespace std::literals;
auto unwrap(std::exception_ptr ptr) -> const std::exception &
{
try {
std::rethrow_exception(ptr);
} catch (std::exception &e) {
return e;
}
}
int main()
{
const auto ptr = std::make_exception_ptr(std::runtime_error{"test"});
const auto &exp = unwrap(ptr);
std::cout << exp.what() << std::endl;
return 0;
}
With GCC, stdout shows "test" which is what I expected. However, with MSVC 2019, stdout shows "Unknown exception".
Is there any undefined, unspecified, or implementation dependent behavior in my source code? Or, is it a compiler/standard library implementation bug?
MSVC makes copies of your exception for some reason. Not sure if this is allowed by the standard or not (someone please clarify). The following code
#include <iostream>
#include <exception>
#include <stdexcept>
using namespace std::literals;
struct myerror : std::runtime_error
{
using std::runtime_error::runtime_error;
myerror(const myerror& o) : myerror(o.what())
{
std::cout << "exception is copied\n";
}
myerror(const myerror&& o) noexcept : myerror(o.what())
{
std::cout << "exception is moved\n";
}
};
auto unwrap(std::exception_ptr ptr) -> const std::exception&
{
try {
std::rethrow_exception(ptr);
}
catch (std::exception const& e) {
std::cout << e.what() << std::endl;
return e;
}
}
int main()
{
std::exception_ptr ptr;
try
{
throw myerror{ "test" };
}
catch (...)
{
ptr = std::current_exception();
}
const auto& exp = unwrap(ptr);
std::cout << exp.what() << std::endl;
return 0;
}
prints with MSVC (16.9):
exception is copied
exception is copied
test
Unknown exception
and with clang:
test
test
So your exception reference is dangling in MSVC's case.
godbolt
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With