json-c库对象释放问题

Posted by Kalos Aner on July 15, 2025

环境: CST 2024 aarch64 aarch64 aarch64 GNU/Linux

头文件: #include <json-c/json.h> 编译选项: gcc xxx.c -o xxx -Wall -g -O0 -std=gnu99 -ljson-c

1. 对象创建函数

函数签名 说明
json_object* json_object_new_object() 创建空 JSON 对象
json_object* json_object_new_array() 创建空 JSON 数组
json_object* json_object_new_string(const char *s) 创建字符串对象
json_object* json_object_new_int(int i) 创建整数对象
json_object* json_object_new_int64(int64_t i) 创建 64 位整数对象
json_object* json_object_new_double(double d) 创建双精度浮点数对象
json_object* json_object_new_boolean(boolean b) 创建布尔对象(b=1 为 trueb=0 为 false
json_object* json_object_new_null() 创建 null 对象

2. JSON 解析函数

函数签名 说明
json_object* json_tokener_parse(const char *str) 解析 JSON 字符串(返回对象指针)
json_object* json_tokener_parse_verbose(const char *str, int *error) 解析 JSON 并返回错误码
json_object* json_object_from_file(const char *filename) 从文件读取并解析 JSON

3. 对象操作函数

对象(Object)操作

函数签名 说明
void json_object_object_add(json_object *obj, const char *key, json_object *value) 添加键值对(存在则替换)
json_object* json_object_object_get(json_object *obj, const char *key) 获取键对应的值对象
int json_object_object_get_ex(json_object *obj, const char *key, json_object **value) 安全获取值对象(返回是否成功)
void json_object_object_del(json_object *obj, const char *key) 删除键值对(释放值对象所有权)

数组(Array)操作

函数签名 说明
int json_object_array_add(json_object *array, json_object *val) 向数组末尾添加元素
json_object* json_object_array_get_idx(json_object *array, int idx) 获取数组指定索引的元素
int json_object_array_put_idx(json_object *array, int idx, json_object *val) 替换/插入数组元素
int json_object_array_length(json_object *array) 获取数组长度

4. 数据提取函数

函数签名 说明
const char* json_object_get_string(json_object *obj) 获取字符串值(自动转换)
int json_object_get_int(json_object *obj) 获取整数值(自动转换)
int64_t json_object_get_int64(json_object *obj) 获取 64 位整数值
double json_object_get_double(json_object *obj) 获取双精度浮点数
int json_object_get_boolean(json_object *obj) 获取布尔值(返回 1/0

5. 类型检查函数

函数签名 说明
enum json_type json_object_get_type(json_object *obj) 返回对象类型(如 json_type_object
int json_object_is_type(json_object *obj, enum json_type type) 检查对象是否为指定类型

6. 序列化函数

函数签名 说明
const char* json_object_to_json_string(json_object *obj) 转换为 JSON 字符串(无格式)
const char* json_object_to_json_string_ext(json_object *obj, int flags) 带格式控制(如 JSON_C_TO_STRING_PRETTY 美化输出)
int json_object_to_file(const char *filename, json_object *obj) 将 JSON 写入文件

7. 内存管理函数

函数签名 说明
int json_object_put(json_object *obj) 减少引用计数(计数为 0 时释放对象)
json_object* json_object_get(json_object *obj) 增加引用计数(防止提前释放)

8. 迭代器与工具

函数签名 说明
json_object_object_foreach(obj, key, val) 宏:遍历对象的所有键值对
int json_object_array_sort(json_object *jarray, int(*sort_fn)(const void*, const void*)) 对数组排序
json_object* json_object_deep_copy(json_object *obj) 深拷贝 JSON 对象

内存空间问题

json 对象在创建时会有一个引用计数,可以使用 json_object_put 来将其引用计数减一,如果其引用计数为零,其空间就会自动释放。我使用 valgrind --leak-check=full ./xxx 对所有常用api的内存问题进行测试。以下“释放”指的是调用 json_object_put 将对象的引用计数减一。

1、json_object_new_object() json_object_new_object 生成的对象必须通过 json_object_put 释放,不然就会内存泄漏。一般情况下,所有的创建类函数都需要手动释放。 2、json_object_get_string(obj) json_object_get_string 会获取 json 对象中的值的指针,无需手动释放内存。 3、多个父对象引用同一个子对象

1
2
3
4
5
6
7
json_object_object_get_ex(parent_obj1, "data", &son_obj);
json_object_object_add(parent_obj2, "data", son_obj);
// 这种情况需要手动增加引用计数如下,如果不手动增加程序会正常运行,但是valgrind报错
json_object_get(son_obj);

json_object_put(parent_obj1);
json_object_put(parent_obj2);

4、json_object_object_get_ex(parent_obj, "data", &son_obj) son_obj 无需手动释放,在释放 parent_obj 时,son_obj 会自动释放。 5、str = (char *)json_object_to_json_string(obj) str 无需手动释放,只需要释放 obj 6、json_object_object_add(parent_obj, "data", son_obj) son_obj 无需手动释放,在释放 parent_obj 时,son_obj 会自动释放。