2

我在我的 c++ 代码中使用 Jansson 库。在库中创建任何 Jansson 变量时,应该释放该变量以释放引用,我正在使用 'json_decref(json_t *json)' 方法来释放。但有时它会导致双重释放问题,而我在运行时没有遇到问题。也许这不正常,但是当我尝试释放一些引用时,我想得到一个运行时错误。例如,我正在运行以下测试代码,

json_t *root = json_loads(any_json_message, 0, &error);
json_decref(root);
json_decref(root);

如您所见,存在问题,并且我没有收到任何运行时错误,例如双重释放。

另外,我正在使用 CMake 来编译我的源代码。也许任何 cmake 标志都可以解决我的问题。

任何想法 ?

4

2 回答 2

1

一旦被释放,访问指向对象的行为是不确定的。文档没有详细说明,但json_decref多次调用(加上您json_incref在指针上调用的次数)也有未定义的行为。

也许这不正常,但是当我尝试释放一些引用时,我想得到一个运行时错误。

好吧,Jansson 不会给你这个。

您的编译器可能会提供一个运行时分析器,它可能能够检测到一些未定义的行为并通过一条消息终止程序。有关如何使用分析器的信息,请参阅编译器的手册。

于 2018-12-30T15:27:48.687 回答
0

文档说json_t包含引用计数。我猜第一次调用json_decref将引用计数从 1 减少到 0 并释放内存。第二次调用json_decref看到引用计数为 0,什么也不做。

要生成双重释放错误,您应该复制json_t对象的旧内容。像这样的东西(但不是字面意思;见下文):

json_t *root = json_loads(any_json_message, 0, &error);
json_t copy = *root;
json_decref(root);
json_decref(&copy);

但是,json_t(我猜)是一种不透明的类型,也就是说,用户只能创建指向它的指针,而不能创建对象。要强制创建对象的副本,您可以猜测json_t对象的大小,然后使用memcpy

json_t *root = json_loads(any_json_message, 0, &error);
char copy[42];
memcpy(copy, root, sizeof copy);
json_decref(root);
json_decref((json_t *)copy);

尝试各种尺寸(而不是 42)直到它起作用。但是,我不确定您是否可以使其工作 - 这只是对该库内部如何工作的猜测。

于 2018-12-30T18:08:53.757 回答