Skip to content

<exception>: constructor does not copy what_arg if _HAS_EXCEPTIONS=0 #2114

Open
@nlohmann

Description

@nlohmann

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:

explicit __CLR_OR_THIS_CALL exception(const char* _Message = "unknown", int = 1) noexcept : _Ptr(_Message) {}

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

Metadata

Metadata

Assignees

No one assigned

    Labels

    bugSomething isn't workingvNextBreaks binary compatibility

    Type

    No type

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions