2

I am using the Jansson library in my c++ code. In the library when any Jansson variable is created, the variable should be freed to release the reference and I am using the 'json_decref(json_t *json)' method to release. But sometimes it causes the double free problem and I didn't get the problem in runtime. Maybe it is not normal but I want to get a runtime error when I try to release some references. For example, I am running the following test code,

json_t *root = json_loads(any_json_message, 0, &error);
json_decref(root);
json_decref(root);

As you see there is a problem and I don't get any runtime error like double free.

Also, I am using CMake to compile my source code. Maybe any cmake flag fixes my question.

Any idea ?

SayMyName
  • 461
  • 5
  • 17
  • 3
    The behavior is *undefined*. There is no guarantee anything will happen if you have a double-free. Just don't write bad code, or learn C++ enough to spot bad code. – PaulMcKenzie Dec 30 '18 at 15:01
  • Another thing to do is learn how to wrap such classes using [RAII](https://stackoverflow.com/questions/2321511/what-is-meant-by-resource-acquisition-is-initialization-raii) techniques, so that you don't have these issues. – PaulMcKenzie Dec 30 '18 at 15:07

2 Answers2

1

The behaviour of accessing the pointed object is undefined once it has been freed. The documentation doesn't spell it out, but calling json_decref more than once (plus the times you've called json_incref on the pointer) also has undefined behaviour.

Maybe it is not normal but I want to get a runtime error when I try to release some references.

Well, Jansson doesn't give that for you.

Your compiler might provide a run time analyser that might be able to detect some undefined behaviour and terminate the program with a message. See the manual of your compiler for how to use the analyser.

eerorika
  • 232,697
  • 12
  • 197
  • 326
0

The documentation says that json_t contains a reference count. I guess that the first call to json_decref decreases the reference count from 1 to 0 and frees the memory. The second call to json_decref sees that the reference count is 0, and does nothing.

To generate the double-free error, you should copy the old contents of the json_t object. Something like this (but not literally; see below):

json_t *root = json_loads(any_json_message, 0, &error);
json_t copy = *root;
json_decref(root);
json_decref(&copy);

However, json_t is (I guess) an opaque type, that is, users can only create pointers to it, and not objects. To force creating a copy of an object, you can guess the size of the json_t object, and use memcpy:

json_t *root = json_loads(any_json_message, 0, &error);
char copy[42];
memcpy(copy, root, sizeof copy);
json_decref(root);
json_decref((json_t *)copy);

Try with various sizes (instead of 42) until it works. However, I am not sure you can make it work - it's just a guess on how the internals of this library work.

anatolyg
  • 26,506
  • 9
  • 60
  • 134
  • Thank you so much for your answer but actually, I don't want to change my attached code. Because my code will be compiled for different platforms with different compilers. The source code won't be changed. – SayMyName Dec 30 '18 at 20:11