Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

json_tokener_parse memory leak? #685

Closed
jclaessens97 opened this issue Dec 8, 2020 · 9 comments
Closed

json_tokener_parse memory leak? #685

jclaessens97 opened this issue Dec 8, 2020 · 9 comments

Comments

@jclaessens97
Copy link

jclaessens97 commented Dec 8, 2020

Describe the bug
I'm using JSON C to parse a relatively large JSON.
I cleaned everything up but when running through Leaks (xcode memoryleak detector), I still get memory leaks.

Steps To Reproduce
I just parse my json with json_object *json = json_tokener_parse(message); where message is the json string.
Then I do calculations, parse it back to a json and put it on a rabbitmq.
I clean everything up I create, and according to the docs I don't need to do manual cleanup for the parse method. However if I run my program through Leaks, I get the following output (see screenshot). Before I did my own cleanup I had 5x the entries, but after doing that all that is left are entries from the json_tokener_parse method.

image

Version and Platform

  • json-c version: json-c-0.15
  • OS: OSX Big Sur 11.0.1 (20B50)
@ploxiln
Copy link
Contributor

ploxiln commented Dec 8, 2020

Can you provide a self-contained code sample?

There might be some confusion: you do need to json_object_put() what json_tokener_parse() returns to you, you just don't have to clean-up the tokener itself, like you would have to if you used json_tokener_new() and json_tokener_parse_ex().

@jclaessens97
Copy link
Author

Sorry for the late response, busy busy...

Below I added a codesample where I don't clean the json at that snippet, but when I try to add the json_object_put(json) at the bottom along the other cleanup calls, it hits the assert for 0 ref_count. However if I debug through it with breakpoints, at that point it says it has a ref_count of 1. If I try to make ownership again (not sure if needed in this case but might as wel try I tought) with json_object_get(), it still doesn't work.. It even makes the memory go up more then without.

It was indeed a bit confusing, but makes sense now.

code snippet:

  json_object *json = json_tokener_parse(message); // message is a json string that comes from rabbitmq

  int rows, cols;
  rows = getNumberOfRows(json);
  cols = getNumberOfCols(json);

  InputParameters input;
  MatrixInputParameters matrix[rows][cols];
  parseMessage(json, rows, cols, &input, matrix);

  OutputValues output[rows][cols];
  for (int i = 0; i < rows; i++) {
    for (int j = 0; j < cols; j++) {
      callModel(&input, &matrix[i][j], &output[i][j]);
    }
  }

  char* outMessage = createMessage(rows, cols, &input, output);
  publishMessage(conn, EVENT_QUEUE, outMessage);

  free(outMessage);
  free(input.simulationUid);

@hawicz
Copy link
Member

hawicz commented Dec 10, 2020

A call to json_object_put() at the end of this code block seems like it would be appropriate. There should be no need to increase the refcount.

If that is the only call to _put() in your code, then the next thing I would suspect is something stomping on memory; running things through a debugger often rearranges things enough to change the behavior for bugs like that.
Does valgrind work on osx? If so, I suggest running your program through that and see if it complains about anything.
Otherwise, I think you'll need to start trimming down your code until you get to a minimal reproduction of the problem, or discover where the bug is by doing so.

@ploxiln
Copy link
Contributor

ploxiln commented Dec 10, 2020

I suspect it might be related to json manipulation in parseMessage() and/or createMessage()

@mansoormemon
Copy link

mansoormemon commented Jan 15, 2021

This is what valgrind shows:

==43719== 7,972 (32 direct, 7,940 indirect) bytes in 1 blocks are definitely lost in loss record 15 of 16
==43719==    at 0x483DD99: calloc (in /usr/lib/x86_64-linux-gnu/valgrind/vgpreload_memcheck-amd64-linux.so)
==43719==    by 0x486E6DC: array_list_new (in /usr/lib/x86_64-linux-gnu/libjson-c.so.4.0.0)
==43719==    by 0x487091D: json_object_new_array (in /usr/lib/x86_64-linux-gnu/libjson-c.so.4.0.0)
==43719==    by 0x4873450: json_tokener_parse_ex (in /usr/lib/x86_64-linux-gnu/libjson-c.so.4.0.0)
==43719==    by 0x48740FA: json_tokener_parse_verbose (in /usr/lib/x86_64-linux-gnu/libjson-c.so.4.0.0)
==43719==    by 0x4874161: json_tokener_parse (in /usr/lib/x86_64-linux-gnu/libjson-c.so.4.0.0)
==43719==    by 0x1096C8: load_items_from_database (item.c:86)
==43719==    by 0x109380: main (main.c:19)
==43719== LEAK SUMMARY:
==43719==    definitely lost: 32 bytes in 1 blocks
==43719==    indirectly lost: 7,940 bytes in 69 blocks

@hawicz
Copy link
Member

hawicz commented Jan 16, 2021

Ok, so json_tokener parsed and allocated an array which didn't get freed. Are you calling json_tokener_put() on the object returned from json_tokener_parse()? If not, then of course you need to do so.
If you are calling _put at some point, then you'll need to look more closely at what you're doing in between the _parse and _put calls.
If you really think it's a bug in the json-c code, then we'll need to see a minimal sample that reproduces the problem, including what you're parsing.

@mansoormemon
Copy link

mansoormemon commented Jan 16, 2021

What is the prototype of json_tokener_put()?

I am using Version: 0.13.1

@hawicz
Copy link
Member

hawicz commented Jan 16, 2021

For 0.13.1 specifically, see http://json-c.github.io/json-c/json-c-0.13.1/doc/html/json__object_8h.html#afabf61f932cd64a4122ca8092452eed5, although it's the same in every version of json-c:

int json_object_put(struct json_object *obj)

For additional details when parsing you can see the json_tokener_parse_ex() docs or for just general json-c usage there's a tutorial over at: https://github.com/rbtylee/tutorial-jsonc/blob/master/tutorial/index.md

@mansoormemon
Copy link

@hawicz Thanks, It worked for me!

@hawicz hawicz closed this as completed Feb 10, 2021
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests

4 participants