如何使用json_incref、json_decref和json_get来查看JSON文件的一部分?

huangapple go评论89阅读模式
英文:

How to use json_incref, json_decref, and json_get to look at a piece of a json file?

问题

我一直在努力理解json_decref和json_incref与json_get函数结合使用的正确方式,以从较大的JSON文件中分离和操作一小部分,而不需要将整个文件保存在内存中。这个问题是在jansson.h库和C编程语言的上下文中提出的。

我的问题是,我在这里是否做对了?在下面的blockload函数中,我是否以正统的方式使用了json_incref和json_decref?我之所以问是因为我在jansson文档和另一个这里的帖子中对json_incref的说明有些困惑。

以下代码片段读取名为"file.json"的文件,其中包含数据:

{"myarray" : [[["aaa","aab","aac"],["aba","abb","abc"],["aca","acb","acc"]],[["baa","bab","bac"],["bba","bbb","bbc"],["bca","bcb","bcc"]],[["caa","cab","cac"],["cba","cbb","cbc"],["cca","ccb","ccc"]]]}

代码片段如下:

#include <stdlib.h>
#include <stdio.h>
#include <unistd.h>
#include <string.h>
#include <jansson.h>

#define INPUTFILE "./file.json"

json_t *blockload(char *inputfile, char *blockname);

int main(void){
    
    json_error_t error;
    json_t *test;
    
    int length;
    
    const char *mystring_const;
    
    json_t *myarray;
    
    json_t *myelement;
    
    myarray = blockload(INPUTFILE, "myarray");
    
    myelement =json_array_get(json_array_get(json_array_get(myarray, 0), 0), 0);
    
    mystring_const = json_string_value(myelement);
    
    printf("%s \n", mystring_const);
    
    json_decref(myarray);
    
    return(0);
    
}
 
json_t *blockload(char *inputfile, char *blockname){
    
    json_error_t error;
    json_t *test, *myarray;
    
    test = json_load_file(INPUTFILE, 0, &error);
    
    myarray = json_object_get(test, blockname);
    
    json_incref(myarray);
    
    json_decref(test);
    
    return(myarray);
}

在这种情况下,我尝试查看与对象"myarray"相关联的数组,但可以想象JSON文件中可能还有许多其他部分,我不想在处理数组时将它们全部保存在内存中。我也不想在主函数中混杂加载感兴趣数组的详细信息,所以我编写了blockload函数来隐藏这些细节。

虽然这段代码能够编译并产生我预期的答案,并且在valgrind中没有产生问题,但我担心它可能仍然包含一些内存使用问题。所以我请教专家们…

英文:

I have been struggling to understand the proper use of json_decref and json_incref in combination with the json_get functions to isolate and manipulate a small piece of a larger json file without keeping the whole thing in memory. This question is in the context of the jansson.h library and the C programming language.

My question is, have I done the right thing here? In this function blockload below, am I using json_incref and json_decref in the orthodox way? I'm asking because I'm having trouble parsing what was said in the jansson documentation about json_incref and also in another posting here.

I have been struggling to understand the proper use of json_decref and json_incref in combination with the json_get functions to isolate and manipulate a small piece of a larger json file without keeping the whole thing in memory. This question is in the context of the jansson.h library and the C programming language.

My question is, have I done the right thing here? In this function blockload below, am I using json_incref and json_decref in the orthodox way? I'm asking because I'm having trouble parsing what was said in the jansson documentation about json_incref and also in another posting here.

The following code snippet reads in a file called "file.json" that has the data

{&quot;myarray&quot; : [[[&quot;aaa&quot;,&quot;aab&quot;,&quot;aac&quot;],[&quot;aba&quot;,&quot;abb&quot;,&quot;abc&quot;],[&quot;aca&quot;,&quot;acb&quot;,&quot;acc&quot;] ],[[&quot;baa&quot;,&quot;bab&quot;,&quot;bac&quot;],[&quot;bba&quot;,&quot;bbb&quot;,&quot;bbc&quot;],[&quot;bca&quot;,&quot;bcb&quot;,&quot;bcc&quot;] ],[[&quot;caa&quot;,&quot;cab&quot;,&quot;cac&quot;],[&quot;cba&quot;,&quot;cbb&quot;,&quot;cbc&quot;],[&quot;cca&quot;,&quot;ccb&quot;,&quot;ccc&quot;] ]]}

The code snippet is as follows

#include &lt;stdlib.h&gt;
#include &lt;stdio.h&gt;
#include &lt;unistd.h&gt;
#include &lt;string.h&gt;
#include &lt;jansson.h&gt;

#define INPUTFILE &quot;./file.json&quot;

json_t *blockload(char *inputfile, char *blockname);

int main(void){
    
    json_error_t error;
    json_t *test;
    
    int length;
    
    const char *mystring_const;
    
    json_t *myarray;
    
    json_t *myelement;
    
    myarray = blockload(INPUTFILE, &quot;myarray&quot;);
    
    myelement =json_array_get(json_array_get(json_array_get(myarray, 0), 0), 0);
    
    mystring_const = json_string_value(myelement);
    
    printf(&quot;%s \n&quot;, mystring_const);
    
    json_decref(myarray);
    
    return(0);
    
}
 
json_t *blockload(char *inputfile, char *blockname){
    
    json_error_t error;
    json_t *test, *myarray;
    
    test = json_load_file(INPUTFILE, 0, &amp;error);
    
    myarray = json_object_get(test, blockname);
    
    json_incref(myarray);
    
    json_decref(test);
    
    return(myarray);
}

In this case, I am trying to look at the array associated with the object "myarray", but one could imagine the json file has many more pieces, and I don't want to have to store them all in memory while I work with the array. I also don't want to clutter up the main routine with the details of how I load in this array of interest, so I have written this function blockload to hide the clutter.

While this code compiles and gives the answer I expect and produces no problems from valgrind, I'm worried it may still contain some memory use issues. So I'm asking the experts...

答案1

得分: 1

json_load_file()是一个对象创建函数。它返回一个新的JSON实体,其类型未指定,并由调用者拥有的引用。该实体的引用计数将为1。

json_object_get()返回指定JSON对象的指定成员的借用引用。由于您计划保留该引用,您应该增加其引用计数,事实上您已经这样做了。只要其引用计数超过0,它就不会被回收。您可以将借用引用的引用计数增加视为将其转换为拥有的引用。

在失去对较大对象的引用之前,您确实做了正确的事情。在任何特定时间知道实际引用计数并不是您的责任,但事实上在这种情况下,您确实知道这将使该对象的引用计数减少为0,从而使其有资格进行清理。

另一方面,您提取的数组的引用计数仍然大于零(因为您增加了它,此时尚未再次减少)。因此,您可以依赖该对象不会被清除。这显然是您设想要实现的目标。

尽管此代码可以编译并给出我期望的答案,并且在valgrind中不会出现问题,但我担心它仍然可能包含一些内存使用问题。

API文档不保证JSON实体实际上会在其引用计数降至零时立即被清除,尽管我希望在通常情况下会是这样。但即使在这种情况下被推迟,Jansson也没有提供更好的替代方案。

在程序终止之前减少数组的引用计数是干净且有效的。在这样做之后,您不应尝试进一步使用该引用,而您的确没有这样做。

您对数组元素和其字符串值的使用在Jansson中也是符合规范的,所以总体而言,一切看起来都很规范。

英文:

json_load_file() is an object creation function. It returns an owned (by the caller) reference to a new JSON entity of unspecified type. The reference count of that entity will be 1.

json_object_get() returns a borrowed reference to the designated member of the specified JSON object. Since you plan to hold on to that reference, you should increase its reference count, which you in fact do. It will not be collected while its reference count exceeds 0. You can think of increasing the reference count of a borrowed reference as converting it into an owned reference.

You indeed do the right thing by decreasing the reference count of the larger object before losing the reference to it. It's not your responsibility to know the actual reference count at any particular time, but in fact you do know in this case that that will decrease the reference count of this object to 0, making it eligible for clean up.

On the other hand, the reference count of the array you pulled out is still above zero (because you increased it and at that point have not decreased it again). You can therefore rely on that object not to be cleaned up. This is apparently what you set out to achieve.

> While this code compiles and gives the answer I expect and produces no problems from valgrind, I'm worried it may still contain some memory use issues.

The API documentation does not guarantee that JSON entities actually will be cleaned up as soon as their reference counts drop to zero, though I expect that will normally be the case. But even if that were deferred in this case, Jansson does not provide a better alternative.

It is clean and valid to decrease the array's reference count before the program terminates. After doing so, you should not attempt to use that reference further, and indeed you don't.

Your use of the array element and its string value are also within the norms for Jansson too, so overall, everything looks by-the-book to me.

huangapple
  • 本文由 发表于 2023年6月29日 06:43:50
  • 转载请务必保留本文链接:https://go.coder-hub.com/76577128.html
匿名

发表评论

匿名网友

:?: :razz: :sad: :evil: :!: :smile: :oops: :grin: :eek: :shock: :???: :cool: :lol: :mad: :twisted: :roll: :wink: :idea: :arrow: :neutral: :cry: :mrgreen:

确定