Должен ли я освободить json_object, возвращаемый json_tokener_parse? - PullRequest
0 голосов
/ 15 января 2019

Я экспериментирую с ошибками памяти в своем C-приложении и использую valgrind, я вижу много странных вещей в json-c lib.

Итак, глядя на некоторые данные в Интернете, я увидел сообщение о json_object_new_object

Итак, у меня есть 2 вопроса, чтобы прояснить все: Первый о конструкции JSON

Когда я добавляю объект к другому объекту, я должен просто освободить первый? Пример:

json_object * jobj1 = json_object_new_object();
json_object * jobj2 = json_object_new_object();

json_object_object_add(jobj1,"Object", jobj2);

...

json_object_put(jobj); // Is it enough to free all the json tree??

Согласно этому сообщению вроде бы все в порядке, но на самом деле ответа не было.

Вопрос 2: Глядя на это tuto , кажется, что ничего не нужно освобождать, но, глядя на мой журнал valgrind, json_object_new_object называется:

by 0x4F7F4CF: json_object_new_object (in /lib/x86_64-linux-gnu/libjson-c.so.3.0.1)
by 0x4F81B38: json_tokener_parse_ex (in /lib/x86_64-linux-gnu/libjson-c.so.3.0.1)
by 0x4F82316: json_tokener_parse_verbose (in /lib/x86_64-linux-gnu/libjson-c.so.3.0.1)
by 0x4F8237D: json_tokener_parse (in /lib/x86_64-linux-gnu/libjson-c.so.3.0.1)

Так я должен сделать это?

json_object *jobj = json_tokener_parse(...);

...

json_object_put(jobj);

1 Ответ

0 голосов
/ 15 января 2019

Документация для json_object_new_object говорит

Помните, что при использовании json_object_object_add или json_object_array_put_idx право собственности переходит к объекту / массиву.

и

Любые права собственности, которые вы приобрели, но не передали, должны быть переданы через json_object_put.

Для меня это означает, что все должно быть в порядке:

json_object *jobj1 = json_object_new_object();
json_object *jobj2 = json_object_new_object();

json_object_object_add(jobj1, "Object", jobj2);

// ...

json_object_put(jobj1); // This is the only one we have ownership of now

И да, как сказано в документации, вы должны освободить все свои права владения, используя json_object_put.

Относительно json_tokener_parse в документации явно ничего не говорится о владении или освобождении, но я был бы очень удивлен, если бы он отличался json_object_new_object в этом отношении. Это не имело бы никакого смысла, если бы вам не разрешали использовать объекты, возвращенные из json_tokener_parse так же, как вы можете использовать объекты, построенные с помощью json_object_new_object.

Например, должно быть возможно сделать это:

json_object *jobj1 = json_object_new_object();  // "Manual" object
json_object *jobj2 = json_tokener_parse(...);   // Parsed object

// At this point, jobj1->_ref_count and jobj2->_ref_count will both be 1.

// We could now add the parsed object as a new field in our "manual" one:
json_object_object_add(jobj1, "ParsedObject", jobj2); 

// ...

// In the end, we only have to release the "manual" object.
json_object_put(jobj1);

Кроме того, да, как показывает ваш журнал valgrind, функция json_tokener_parse вызывает json_object_new_object за кулисами, поэтому вам нужно вызвать json_object_put для возвращаемого объекта (т.е., если вы не включите его в другой объект или массив , как упоминалось ранее).

Парень, который написал код в упомянутом сообщении в блоге , похоже, не заботится об утечке памяти в своей программе, возможно, потому что эта программа настолько проста и заканчивается сразу после обработки только одного объекта.

...