13

I have the following code

#include <stdio.h>
#include <stdlib.h>
#include <stddef.h>
#include <string.h>

#include <json/json.h>

int main(int argc, char **argv)
{
      json_object *new_obj;
      char buf[] = "{ \"foo\": \"bar\", \"foo2\": \"bar2\", \"foo3\": \"bar3\" }";
      new_obj = json_tokener_parse(buf);
      .....
      json_object_put(new_obj);
}

Does the json_object_put(new_obj) free all memory related to new_obj ?

Tõnu Samuel
  • 2,877
  • 2
  • 20
  • 30
MOHAMED
  • 41,599
  • 58
  • 163
  • 268

2 Answers2

8

From the documentation:

void json_object_put    (struct json_object *this)  

Decrement the reference count of json_object and free if it reaches zero

Source: http://oss.metaparadigm.com/json-c/doc/html/json__object_8h.html

djechlin
  • 59,258
  • 35
  • 162
  • 290
  • 3
    I know this. I m looking a confirmation that json_object_put free the meomry in the example I put – MOHAMED Feb 14 '13 at 16:59
  • So you're asking how to verify that free'd memory is actually free'd? That's a totally different question. – djechlin Feb 14 '13 at 17:01
  • 6
    I too found this an interesting question. The name of the function is unexpected ... I have no intuitive understanding that "put" means to decrement the reference count and free if needed. – Kolban Jul 06 '16 at 23:42
  • Does json_object_put free the nested object, or do we need to to call it for all the nested objects? – Jagadeesh Jun 08 '20 at 11:51
  • 1
    json_object_put works recursively; if all of the nested objects start with a refcount of 1 (the common case), then it will free them. However, if you've plucked out a subtree from the main object and explicitly incremented its refcounts then that hierarchy will continue to live until you call json_object_put on it. – Eric Aug 07 '20 at 14:04
  • I know of at least one json-c tutorial, which seems pretty decent, and might help gain an understanding of how to use the library: https://github.com/rbtylee/tutorial-jsonc/blob/master/tutorial/index.md – Eric Aug 09 '20 at 17:50
-1

You have to understand how the library works.

json_tokener_parse() is first, and it creates an object that will act as a memory managing parent that all objects which are created from it use to access the data they define.

So if you get all the way down to making a char *str for a string field, that field doesn't actually store the string, the original object returned from json_tokener_parse() does.

This is the reason that you can't just use a normal free() and expect things to work as if it was a char array or something.

To be safe, don't use the json_tokener_parse_ex() function because you will have to also free the object that is the tokener, with json_tokener_parse() you don't need that argument.

Beyond that, to safely close everything just do:

while (json_object_put(orig_object) != 1) {
  // keep freeing
}

You should only need to do that once, but the library may change.

  • This is terrible advice. There is nothing "unsafe" about json_tokener_parse_ex(), and you definitely should *not* be calling json_object_put in a loop. – Eric Aug 07 '20 at 14:00
  • Eric, you have an issue with ideals. Obviously that's ideally true, but with this library you need to understand that the free routine for the token does have a memory leak which fails eventually. You certainly still don't understand the compiler. The while loop that tests for the output of the command in the loop only runs when it needs to, it is the ideal way to do things as the function failing or succeeding stops the loop as it uses a signed integer, not an unsigned integer as the return value. You cannot mathematically beat that, I have no idea why you are complaining. – Andrew Hodel Aug 08 '20 at 15:25
  • Compiler? malloc & free? Rules for library apis? They're all the same thing, right? I guess since I think they're different I must not "understand the compiler". So, go ahead, call json_object_put indiscriminately, while you're at it call free a few dozen times on the other blocks of memory, and make sure to keep accessing the chunks afterwards, I'm sure it'll all be fine. /s Please stop spreading lies about non-existant memory leaks. – Eric Aug 09 '20 at 17:45
  • Yea, the compiler converts the while loop into an absolute non-while loop based on the code in the put() function. Without a doubt, there is absolutely no way it can fail. – Andrew Hodel Aug 10 '20 at 18:05