Question

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 } }
Was it helpful?

Solution

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:

  • change the type of cstr to std::string and it will copy the returned const char*, or
  • Make of a copy of the Value 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.

Licensed under: CC-BY-SA with attribution
Not affiliated with StackOverflow
scroll top