Description
Describe the bug
When _HAS_EXCEPTIONS
is defined to 0
, the constructors of the exception classes do not copy the what_arg
, but only store the pointer:
Line 90 in 4721611
This leads to errors if the pointee is a temporary string.
If _HAS_EXCEPTIONS
is set to 1
, a copy is made just as the standard would require it.
Command-line test case
The following code outputs [json.exception.parse_error] foo
if _HAS_EXCEPTIONS
is set to 1
, and some garbage if _HAS_EXCEPTIONS
is set to 0
:
#include <exception> // exception
#include <stdexcept> // runtime_error
#include <string> // string
#include <iostream> // cout
namespace nlohmann
{
namespace detail2
{
class exception : public std::exception
{
public:
const char* what() const noexcept override
{
return m.what();
}
protected:
exception(const char* what_arg) : m(what_arg) {}
private:
std::runtime_error m;
};
class parse_error : public exception
{
public:
static parse_error create(const std::string& what_arg)
{
std::string w = "[json.exception.parse_error] " + what_arg;
return parse_error(w.c_str());
}
private:
parse_error(const char* what_arg) : exception(what_arg) {}
};
} // namespace detail2
} // namespace nlohmann
int main()
{
auto error = nlohmann::detail2::parse_error::create("foo");
std::cout << error.what() << std::endl;
}
The example comes from https://github.com/nlohmann/json where exceptions are created by a SAX parser, but it is up to the client whether they are thrown or not. Therefore, using exception classes while disabling throwing exceptions is a usecase.
Expected behavior
The exception makes a copy of the what_arg
argument, regardless of the value of _HAS_EXCEPTIONS
.
STL version
I could reproduce the issue with MSVC 19.16.27045.0 and MSVC 19.29.30040.0.
Additional context
The issue was originally found here: nlohmann/json#2824