【问题标题】:Do I have to free json_object returned by json_tokener_parse?我是否必须释放 json_tokener_parse 返回的 json_object?
【发布时间】:2019-01-15 15:30:56
【问题描述】:

我正在我的 C 应用程序中试验内存错误并使用 valgrind,我在 json-c 库周围看到了许多奇怪的东西。

所以看了网上的一些信息,我看到了这个post关于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??

根据这个post 似乎还可以,但还没有真正得到答复。

问题 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);

【问题讨论】:

    标签: json-c


    【解决方案1】:

    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(即,除非您将其合并到另一个对象或数组中,如前所述)。

    在引用的blog post 中编写代码的人似乎并不关心他的程序中的内存泄漏,可能是因为该程序非常简单,只处理一个对象后立即结束。

    【讨论】:

    • 非常感谢您的回答。您是否还确认在我们完成json_tokener_parse 后必须调用json_object_put
    • @fralbo:是的,我已经更新了我的答案以解决关于 json_tokener_parse 的部分。我还通过在github.com/json-c/json-c 实际查看 json-c 的源代码来验证我的声明
    • 请不要使用上面提到的文档链接,而是从json-c.github.io/json-c开始。
    猜你喜欢
    • 2011-12-15
    • 2021-09-15
    • 1970-01-01
    • 1970-01-01
    • 2011-05-19
    • 1970-01-01
    • 1970-01-01
    • 2012-11-21
    相关资源
    最近更新 更多