open-source-parsers / jsoncpp

A C++ library for interacting with JSON.
Other
8.15k stars 2.64k forks source link

std::out_of_range raised when accessing std::map with Json::Value::asCString() as key #1454

Closed stachurr closed 1 year ago

stachurr commented 1 year ago

I have a map of const char*'s to MyFunc_t's that I'm using to look up the function associated with the given string. When I try to access this map using the result from Json::Value::asCString() an std::out_of_range exception is thrown, even though it is equivalent to the const char* (as verified with strcmp).

I hoped that assigning the result like const char *str = val.asCString() would solve the problem, but the issue persists.

Here exists the bare minimum code required to provide context:

/* A map, used to get a pointer to a function from some text */
std::map<const char*, MyFunc_t> my_map = {
    {"example", &myFunc}
};

/* The raw string to be parsed */
std::string payload = "{\"some_key\":\"example\"}";

/* Parsing the string */
Json::Reader reader(Json::Features::strictMode());
Json::Value root;
reader.parse(payload, root, false);
// reader.good() => true

/* Some troubleshooting I've used to verify I'm not crazy... */
Json::Value val = root.get("some_key", Json::Value::null);
// val.isNull() => false
// strcmp("example", val.asCString()) => 0

Running the following code works as expected and does not raise any errors:

MyFunc_t f = my_map.at("example");
f();

However, when I try to use Json::Value::asCString(), an out of range exception is raised:

MyFunc_t f = my_map.at(val.asCString());
f();

I expected the function pointer to be returned, but this is not the case.

stachurr commented 1 year ago

This issue does not occur when using std::string and asString()...

BillyDonahue commented 1 year ago

Ah. This is a std::map usage error, not a JsonCpp problem.

The const char* key is a pointer type, not a string type. The std::map is going to use pointer operator < for the lookup, and doesn't consider the pointee at all. So that val.asCString() pointer is indeed not in the map, which is being correctly reported by the exception.