I have a condition I cannot explain when using Jansson in a C application. Here is an example of the code:
{
"nodes": {
"master": "10.0.0.9",
"connected": [
{
"socket": 18,
"IP": "10.0.0.9"
}
]
}
}
Code snippet
STATUS writeMasterNode(char *newMaster)
{
static char configFilename[] = "/path/to/file.json";
obj = json_load_file(configFilename, 0, &error);
// check to see if the string parsed fine
if (!obj)
{
printf("Error parsing system configuration on line %d, column %d:%s", error.line, error.column, error.text);
return;
}
// read the object into a temporary json objects
node_obj = json_object_get(obj, "nodes");
if (!node_obj)
{
node_obj = json_pack("{{s:s},[{s:i},{s:s}]}", "master", NULL, "socket", NULL, "IP", NULL);
}
master_obj = json_object_get(node_obj, "master");
connected_obj = json_object_get(node_obj, "connected");
//Update
//************* Good code ***************
master_obj = json_string(newMaster);
json_object_set(node_obj, "master", master_obj);
//***************************************
//
//************* Bad Code ***************
//json_object_set(node_obj, "master", json_string(newMaster))
//**************************************
//
json_object_set(obj, "nodes", node_obj);
//Write
if (!obj)
{
printf("Error parsing system configuration on line %d, column %d:%s", error.line, error.column, error.text);
return;
}
else
{
json_dump_file(obj, configFilename, JSON_INDENT(2));
}
//Cleanup
json_decref(obj);
json_decref(node_obj);
son_decref(connected_obj);
json_decref(master_obj);
}
If I use:
json_object_set(node_obj, "master", json_string(newMaster))
the app will update the file and seem fine until I recall this block of code, then it will crash upon second usage.
Changing the offending code line with:
master_obj = json_string(newMaster);
json_object_set(node_obj, "master", master_obj);
works fine and I can recall this function over and over without issue. Any ideas?
When you run the bad code:
master_obj = json_object_get(node_obj, "master");
...
json_object_set(node_obj, "master", json_string(newMaster))
...
json_decref(node_obj);
json_decref(master_obj);
The master_obj
is borrowed reference from node_obj
, and it is already freed, when json_decref(master_obj)
is called.
The good code:
master_obj = json_object_get(node_obj, "master");
...
master_obj = json_string(newMaster);
json_object_set(node_obj, "master", master_obj);
...
json_decref(node_obj);
json_decref(master_obj);
A new json_string object is created and pointer is stored to master_obj
.
The json_string object still exists when you call json_decref(master_obj)
, so it does not cause the issue.