I'm using Json-cpp to parse my config file and I get som weird behavior with asCString().. Can anyone explain why output of 2 is empty?
#include <iostream>
#include <fstream>
#define JSON_IS_AMALGAMATION
#include "json/json.h"
using std::cout;
using std::endl;
int main(int argc, char** argv) {
Json::Value root;
Json::Reader reader;
std::ifstream config("dev.json", std::ifstream::binary);
if (!reader.parse(config, root, false)) {
cout << "Could not parse json" << endl;
return 1;
}
std::string str = root["redis"].get("host", "localhost").asString();
const char* cstr = root["redis"].get("host", "localhost").asCString();
cout << "1:" << str << endl;
cout << "2:" << cstr << endl;
cout << "3:" << std::string(root["redis"].get("host", "localhost").asCString()) << endl;
config.close();
return 0;
}
Output:
c++ -o test test.cpp jsoncpp.cpp
1:127.0.0.2
2:
3:127.0.0.2
My json data:
{ "redis": { "host": "127.0.0.2", "port": 6379 } }
I suspect that root["redis"].get("host", "localhost")
or root["redis"]
returns a Value
, not a reference to a Value
. That Value
object will live until the end of the expression, in the case of 2
the temporary Value
object will be destroyed, leaving cstr
as a dangling pointer. The behaviour is undefined when dereferencing a dangling pointer.
In the case of 1
, the str
is a copy of the std::string
returned by asString()
.
In the case of 3
, the temporary Value
will survive until the end of the expression (the ;
) allowing the const char*
returned by asCString()
to be successfully processed.
To solve, either:
cstr
to std::string
and it will copy the returned const char*
, orValue
returned by get()
and query it rather than root[]
.EDIT:
Based on this source, all variants of Value.get()
return a Value
. So the cause is as described.