我正在使用 janson 库发送 json 正文作为其余请求,我注意到我正在这样做:
json_t *json_body = json_object();
char sentString[100];
char sentStringSecond[100];
..
json_object_set_new(json_body, "sentString", json_string(sentString));
json_object_set_new(json_body, "sentStringSecond", json_string(sentStringSecond);
..
json_decref(json_body);
对 json_decref 的一次调用是否足以释放所有内存? 我的担忧主要是读完这篇文章后 json_decref 不释放内存?
您正在使用不同的函数来设置 JSON 字符串:
json_object_set_new
而不是链接问题中的 json_object_set
。
您的版本将元素添加到 json 对象并“重用”引用。它不会增加计数器。 因此您不需要手动递减它。 该问题答案下面的评论也提到了
json_object_set_new
。
添加的元素将与主 JSON 对象一起被释放
json_body
。
这意味着所有子对象的引用计数器都会自动递减。如果计数器降至 0,则该对象被释放。
如果您自己持有对子对象的引用,则该对象将不会被释放。
举个例子:
您创建一个对象(调用
json_string()
),它将获得引用计数==1。
变体a)(来自链接的问题)
您可以将此对象添加到具有新引用的另一个对象。 这是使用
json_object_set
完成的。然后计数器增加到 2。
如果删除主对象(
json_decref(json_body)
),计数器再次降至1,但字符串仍然没有释放。
您需要使用 json_decref(srting)
来释放内存。
变体 b)(您的代码)
您可以将此对象添加到另一个对象并移交现有引用。 这是使用
json_object_set_new
完成的。然后计数器保留值 1。
如果删除主对象 (
json_decref(json_body)
) 计数器将降至 0,现在字符串与主对象一起被释放。
您不需要使用 json_decref(srting)
来释放内存。
当我们在jansson库中创建一个json对象时,它的类型是'json_t'。该库使用引用计数来管理对象的清理。内部调用malloc和free进行内存管理;每当我们创建一个对象 json_t * obj 时,都会分配内存,并且在引用计数不为空之前不会释放该对象。
文档中经常提到的术语“窃取引用”意味着对象引用计数被借用,并且一旦对象被消耗,计数就不会增加。因此,lib 中的所有“.._new” api 都可以让您以更干净的方式编写,而无需大惊小怪 decref - json 对象中的各个元素。
我自己必须阅读文档和示例才能为此 json_decref 创建这个综合答案。我试图保持简单并使用 valgrind 来获得更好的理解。以下是示例:
#include <stdio.h>
#include <stdlib.h>
#include <jansson.h>
int main(){
int a =5;
//char * str = malloc(sizeof(a)*4);
printf("str allocated\n");
json_t * obj = json_object();
json_t * obj2 = json_object();
json_object_set_new(obj, "node", obj2);
json_object_set_new(obj, "num", json_integer(a));
json_object_set_new(obj, "num", json_integer(a));
json_object_set_new(obj2, "num3", json_integer(2));
json_object_set_new(obj2, "num4", json_integer(28));
json_object_set_new(obj, "str", json_string("name"));
char * s = json_dumps(obj, JSON_COMPACT | JSON_INDENT(2));
printf("json is [%s]", s);
free(s);
//json_decref(obj);
json_decref(obj2);
return 0;
}
charulata@charulata-virtual-machine:~$ vi test_val_json.c
charulata@charulata-virtual-machine:~$ gcc -o json_v test_val_json.c -ljansson
charulata@charulata-virtual-machine:~$ valgrind ./json_v
==5676== Memcheck, a memory error detector
==5676== Copyright (C) 2002-2017, and GNU GPL'd, by Julian Seward et al.
==5676== Using Valgrind-3.18.1 and LibVEX; rerun with -h for copyright info
==5676== Command: ./json_v
==5676==
str allocated
json is [{
"node":{
"num3":2,
"num4":28
},
"num":5,
"str":"name"
}]==5676==
==5676== HEAP SUMMARY:
==5676== in use at exit: 418 bytes in 8 blocks
==5676== total heap usage: 24 allocs, 16 frees, 2,378 bytes allocated
==5676==
==5676== LEAK SUMMARY:
==5676== definitely lost: 72 bytes in 1 blocks
==5676== indirectly lost: 346 bytes in 7 blocks
==5676== possibly lost: 0 bytes in 0 blocks
==5676== still reachable: 0 bytes in 0 blocks
==5676== suppressed: 0 bytes in 0 blocks
==5676== Rerun with --leak-check=full to see details of leaked memory
==5676==
==5676== For lists of detected and suppressed errors, rerun with: -s
==5676== ERROR SUMMARY: 0 errors from 0 contexts (suppressed: 0 from 0)
#include <stdio.h>
#include <stdlib.h>
#include <jansson.h>
int main(){
json_t * res = json_object();
json_object_set_new(res, "state", json_string("up"));
json_t * jcards = json_array();
json_object_set_new(res, "cards", jcards);
for ( int i = 0; i <2; i++){
int a =5;
//char * str = malloc(sizeof(a)*4);
printf("str allocated\n");
json_t * obj = json_object();
json_array_append_new(jcards, obj);
json_object_set_new(obj, "num", json_integer(a));
json_object_set_new(obj, "num", json_integer(a));
json_object_set_new(obj, "num3", json_integer(2));
json_object_set_new(obj, "num4", json_integer(2));
json_object_set_new(obj, "str", json_string("name"));
json_t * new = json_object_get(res, "cards");
char * k = json_dumps(new, JSON_COMPACT | JSON_INDENT(2));
printf("json is [%s]", k);
free(k);
char * s = json_dumps(obj, JSON_COMPACT | JSON_INDENT(2));
printf("json is [%s]", s);
free(s);
//json_decref(obj); /*not required as parent obj is being cleaned*/
}
//json_decref(jcards); /*not required as parent obj is being cleaned, arr is part of json obj here 'res'*/
json_decref(res);
return 0;
}
charulata@charulata-virtual-machine:~$ vi test_json_arr_obj.c
charulata@charulata-virtual-machine:~$ gcc -o json_arr test_json_arr_obj.c -ljansson
charulata@charulata-virtual-machine:~$ valgrind ./json_arr
==5798== Memcheck, a memory error detector
==5798== Copyright (C) 2002-2017, and GNU GPL'd, by Julian Seward et al.
==5798== Using Valgrind-3.18.1 and LibVEX; rerun with -h for copyright info
==5798== Command: ./json_arr
==5798==
str allocated
json is [[
{
"num":5,
"num3":2,
"num4":2,
"str":"name"
}
]]json is [{
"num":5,
"num3":2,
"num4":2,
"str":"name"
}]str allocated
json is [[
{
"num":5,
"num3":2,
"num4":2,
"str":"name"
},
{
"num":5,
"num3":2,
"num4":2,
"str":"name"
}
]]json is [{
"num":5,
"num3":2,
"num4":2,
"str":"name"
}]==5798==
==5798== HEAP SUMMARY:
==5798== in use at exit: 0 bytes in 0 blocks
==5798== total heap usage: 63 allocs, 63 frees, 4,750 bytes allocated
==5798==
==5798== All heap blocks were freed -- no leaks are possible
==5798==
==5798== For lists of detected and suppressed errors, rerun with: -s
==5798== ERROR SUMMARY: 0 errors from 0 contexts (suppressed: 0 from 0)
#include <stdio.h>
#include <stdlib.h>
#include <jansson.h>
int main(){
int a =5;
json_t * obj = json_object();
//json_object_set_new(obj, "num3", json_integer(2));
json_object_set(obj, "num3", json_integer(2)); /*this json_integer object is not freed*/
json_object_set_new(obj, "num4", json_integer(2));
json_object_set_new(obj, "str", json_string("name"));
char * s = json_dumps(obj, JSON_COMPACT | JSON_INDENT(2));
printf("json is [%s]", s);
free(s);
json_decref(obj);
return 0;
}
charulata@charulata-virtual-machine:~$ vi test_json_set_new.c
charulata@charulata-virtual-machine:~$ gcc -o json_s_new test_json_set_new.c -ljansson
charulata@charulata-virtual-machine:~$ valgrind ./json_s_new
==6274== Memcheck, a memory error detector
==6274== Copyright (C) 2002-2017, and GNU GPL'd, by Julian Seward et al.
==6274== Using Valgrind-3.18.1 and LibVEX; rerun with -h for copyright info
==6274== Command: ./json_s_new
==6274==
json is [{
"num3":2,
"num4":2,
"str":"name"
}]==6274==
==6274== HEAP SUMMARY:
==6274== in use at exit: 24 bytes in 1 blocks
==6274== total heap usage: 16 allocs, 15 frees, 1,808 bytes allocated
==6274==
==6274== LEAK SUMMARY:
==6274== definitely lost: 24 bytes in 1 blocks
==6274== indirectly lost: 0 bytes in 0 blocks
==6274== possibly lost: 0 bytes in 0 blocks
==6274== still reachable: 0 bytes in 0 blocks
==6274== suppressed: 0 bytes in 0 blocks
==6274== Rerun with --leak-check=full to see details of leaked memory
==6274==
==6274== For lists of detected and suppressed errors, rerun with: -s
==6274== ERROR SUMMARY: 0 errors from 0 contexts (suppressed: 0 from 0)
#include <stdio.h>
#include <stdlib.h>
#include <jansson.h>
int main(){
int a =5;
json_t * obj = json_object();
json_t *val = json_integer(2);
json_object_set(obj, "num3", val); /*this json_integer object is not freed by itself, exclusively decref is called for this element*/
json_object_set_new(obj, "num4", json_integer(3));
json_object_set_new(obj, "str", json_string("name"));
char * s = json_dumps(obj, JSON_COMPACT | JSON_INDENT(2));
printf("json is [%s]", s);
free(s);
json_decref(obj);
json_decref(val);
return 0;
}
charulata@charulata-virtual-machine:~$ gcc -o json_s_new test_json_set_new.c -ljansson
charulata@charulata-virtual-machine:~$ valgrind ./json_s_new
==6515== Memcheck, a memory error detector
==6515== Copyright (C) 2002-2017, and GNU GPL'd, by Julian Seward et al.
==6515== Using Valgrind-3.18.1 and LibVEX; rerun with -h for copyright info
==6515== Command: ./json_s_new
==6515==
json is [{
"num3":2,
"num4":3,
"str":"name"
}]==6515==
==6515== HEAP SUMMARY:
==6515== in use at exit: 0 bytes in 0 blocks
==6515== total heap usage: 16 allocs, 16 frees, 1,808 bytes allocated
==6515==
==6515== All heap blocks were freed -- no leaks are possible
==6515==
==6515== For lists of detected and suppressed errors, rerun with: -s
==6515== ERROR SUMMARY: 0 errors from 0 contexts (suppressed: 0 from 0)
#include <stdio.h>
#include <stdlib.h>
#include <jansson.h>
int main(){
int a =5;
json_t * obj = json_object();
json_t *val = json_integer(2);
json_object_set(obj, "num3", val); /*this json_integer object is not freed by itself, exclusively decref is called for this element*/
json_object_set_new(obj, "num3", val); /*this json_integer object is freed by itself*/
json_object_set_new(obj, "num4", json_integer(3));
json_object_set_new(obj, "str", json_string("name"));
char * s = json_dumps(obj, JSON_COMPACT | JSON_INDENT(2));
printf("json is [%s]", s);
free(s);
json_decref(obj);
//json_decref(val);
return 0;
}
charulata@charulata-virtual-machine:~$ gcc -o json_s_new test_json_set_new.c -ljansson
charulata@charulata-virtual-machine:~$ valgrind ./json_s_new
==6533== Memcheck, a memory error detector
==6533== Copyright (C) 2002-2017, and GNU GPL'd, by Julian Seward et al.
==6533== Using Valgrind-3.18.1 and LibVEX; rerun with -h for copyright info
==6533== Command: ./json_s_new
==6533==
json is [{
"num3":2,
"num4":3,
"str":"name"
}]==6533==
==6533== HEAP SUMMARY:
==6533== in use at exit: 0 bytes in 0 blocks
==6533== total heap usage: 16 allocs, 16 frees, 1,808 bytes allocated
==6533==
==6533== All heap blocks were freed -- no leaks are possible
==6533==
==6533== For lists of detected and suppressed errors, rerun with: -s
==6533== ERROR SUMMARY: 0 errors from 0 contexts (suppressed: 0 from 0)