为什么我的代码在添加 aSan 库后不再崩溃?

Why does my code stop crashing after adding aSan library?

我目前正在调试 C 代码。这基本上是来自数据收集平台的客户端,我从链表中读取了奇怪的错误。问题基本上是最后一项的 "next" 指针在某个未知点从 NULL 更改为 0xFFFFFFFFF。然后我尝试用address sanitizer编译我的库,以便找到bug bug可能在哪里并且bug消失了,或者最好说bug当前是隐藏的。可能吗? Asan 库如何影响代码以使其不崩溃?提前致谢。

编辑: 抱歉描述不佳,我会尝试更深入。我一直在调试代码,我找到了问题所在。它位于 json 配置文件的解析函数中(为此我使用 jansson 库)。 json格式是这样的:

{
...
"version": {
            "software": "0.2",
            "firmware": "0.2"
        },     
"system": ["system_A", "system_B"],
...
"internal_devices : [
         {
             ...
             "version": {
                 "software": "0.2",
                 "firmware": "0.2"
             },     
             "system": ["system_B"],
             ...
             },
             ...
             "version" : {
                 "software": "0.2",
                 "firmware": "0.2"
              },     
              "system": ["system_A"],
               ...
               }
           ]
      }
}   

我有一个这样的结构来存储这些数据

typedef struct XXX_NODE {
    mqtt_client_t * client;
    XXX_Device devices[XXX_MAX_DEVICES];
    size_t num_devices;
    XXX_operation_mode mode;
    pthread_mutex_t callback_lock;
    pthread_mutex_t registration_lock;
    pthread_cond_t registration_condition;
}XXX_NODE;

typedef struct XXX_id {
    ...
    struct XXX_parent parent_unit;
    // char parent_fin[64];
    int internal_level_tree;
    XXX_version version;
    List XXX_systems;
    List extended_topics;
    bool registered;
}XXX_id;

真正的问题在清单XXX_systems中。每个设备我都有一个列表,我可以在同一个结构中有多个设备,其中第一个元素(在 XXX_Device 设备数组中)是主要单元。正是在这个设备中,我丢失了信息。解析函数看起来工作正常。在函数的末尾,该结构具有权限值,但是当我释放 json "objects" 时,我丢失了 XXX_systems->next 的引用,但奇怪的是如果我不这样做免费一些 json "objects",一切正常...

因此,在这种情况下,我丢失了信息:

json_decref(internal_list);
json_decref(unit);
json_decref(root);
return 0;

但是如果我这样评论json_decref

json_decref(internal_list);
//json_decref(unit);
json_decref(root);
return 0; 

一切正常...

根据您的描述,对 json_decref() 的调用似乎会导致数据损坏。显然,由 unit 变量标识的一些数据被破坏了,然后你试图使用它,可能来自一些单独的代码。

我可以看到两种最有可能的情况:

  • 要么您有超过一个 'user' 的一些数据,您可能不关心在 'users' 中正确识别 'owner',因此有人决定删除仍在使用的数据;
  • 或者,您忘记了识别某些用户,因此某个数据对象在某些时候似乎未被使用,并在有人仍在引用它时被删除。

我对根本的 Jansson 问题一无所知,但我只是询问了 Google 关于 json_decref 的问题,它找到了 Jansson 库描述。请参阅引用计数部分:

https://jansson.readthedocs.io/en/2.8/apiref.html#reference-count

那里清楚地说明了 json_decref() 减少引用计数并在计数降为零时删除对象。以下说明描述了创建所谓的 借用引用 并指出此类引用的持有者必须调用 json_incref()。这可以防止对象在使用时被删除。一旦不再需要该值,就应该调用 json_decref() 来释放引用(并且可能删除数据对象)。

结论是您很可能错过了 json_incref() 存储供将来使用的参考的代码段。结果,引用计数太低并且过早归零,导致过早删除。这是第二个场景。

扫描代码和数据结构以查找对 Json 数据对象的存储引用,并确保每次存储非空引用时都调用 json_incref(),并且每次非空引用空引用被覆盖或超出您调用的范围 json_decref().

注意:
仔细区分 借用的参考文献 被盗的参考文献 – 后者在链接文档页面中也有描述。

P.S.
看来您的问题与 C 语言无关,而是与 Jansson 库使用不当有关。请考虑删除不必要的 标签。