You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

Jansson库json_decref异常行为及引用管理问题咨询

关于Jansson库json_decref使用的疑问解答

先直接理清Jansson引用计数的核心规则,这是解决你问题的关键:

  • 拥有所有权的引用:通过json_load_file、json_object_new、json_integer等创建对象的函数返回的引用,你需要负责调用json_decref来释放。
  • 借用引用:通过json_object_get、json_array_get等获取对象中元素的函数返回的引用,你不需要调用json_decref,因为所有权仍然属于原对象(比如你的parObj)。

问题1:为什么cleanJson()后getAccountId仍能返回旧值?

当你调用cleanJson()执行json_decref(parObj)时,只是把parObj的引用计数减1。如果这是最后一个引用,Jansson会释放parObj占用的内存,但被释放的内存并不会立即被操作系统清空或覆盖——你的程序此时访问这块内存,可能还能读到之前存储的值,这属于未定义行为。

这种情况完全是巧合,下次运行程序可能就会返回随机值、崩溃,或者返回null,不能依赖这个结果。你预期的“返回错误或null”是合理的,但未定义行为的表现本身就是不确定的。

问题2:给json_acc和json_param加json_decref导致提前崩溃

json_acc是json_object_get(parObj, "accounts")返回的借用引用,json_param同理——它们的所有权都属于parObj。如果你对它们调用json_decref,会错误地减少它们的引用计数,可能导致这些子对象被提前释放。

当后续代码(甚至是json_object_get内部)访问已经被释放的内存时,就会触发崩溃。崩溃点不一定在你预期的a_test调用环节,因为内存损坏的影响是连锁且不确定的,可能在第一次访问被破坏的对象时就崩溃了。


正确的代码示例

你的核心代码只需要在parObj上调用一次json_decref即可,不需要处理json_acc和json_param:

API侧修正后代码

json_t* parObj; 

void loadFile(char* path) { 
    json_error_t error; 
    // 如果parObj之前已经有值,要先释放避免内存泄漏
    if (parObj) {
        json_decref(parObj);
    }
    parObj = json_load_file(path, 0, &error); 
} 

int getAccountId(char* id) { 
    if (!parObj) {
        // 处理parObj已被释放或未加载的情况
        return -1; // 或者其他错误标识
    }
    json_t* json_acc = json_object_get(parObj, "accounts"); 
    if (!json_acc || !json_is_object(json_acc)) {
        return -1;
    }
    json_t* json_param = json_object_get(json_acc, id); 
    if (!json_param || !json_is_integer(json_param)) {
        return -1;
    }
    return json_integer_value(json_param); 
} 

void cleanJson() { 
    if (parObj) {
        json_decref(parObj);
        parObj = NULL; // 置空,避免后续误访问已释放的指针
    }
} 

调用侧修正后代码

loadFile("/home/jacob/accountDump.json"); 
int a_id = getAccountId("10"); 
cleanJson(); 
int a_test = getAccountId("10"); // 此时会返回-1,符合预期

这样修改后,cleanJson()会把parObj置空,后续调用getAccountId会先检查parObj是否有效,避免访问已释放的内存。

内容的提问来源于stack exchange,提问作者Jacob

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.05.28 06:52:57