json-c 中 调用 json_object_put()后的诡异现象

zz_d 2012-08-20 04:56:29
以下是我的gdb跟踪:

---------------------------------------------------
369 json_object_put(pobj2);
(gdb) display g_config->host_info
1: g_config->host_info = {ip = "10.1.14.221\000\000\000\000", port = 80,
posturl = 0x8056930 "/falconconsole/server.php",
hearturl = 0x8056960 "/falconconsole/server.php",
config_dir = 0x80569d0 "/falconconsole/configfile/"}
(gdb) n
372 pobj2 = json_object_object_get(pobj, "heartperiod");
1: g_config->host_info = {ip = "10.1.14.221\000\000\000\000", port = 80,
posturl = 0x8056930 "/falconconsoke/server.php",
hearturl = 0x8056960 "/falconconsoke/server.php",
config_dir = 0x80569d0 "/falconconsole/configfile/"}

------------------------------------------------------

在执行完 json_object_put(pobj2) 后, posturl 和 hearturl 中的 falconconsole 都变成了 falconsoke .

求指教.


...全文
1580 6 打赏 收藏 转发到动态 举报
写回复
用AI写文章
6 条回复
切换为时间正序
请发表友善的回复…
发表回复
zz_d 2012-08-22
  • 打赏
  • 举报
回复
应该是我 json_object_put() 使用有误了.

jsonc 库是一个c的json库, 最近一直用它, 有些使用过程的想法, 写在这里.

使用c库最关心的是内存谁来分配, 谁来释放. jsonc的内存管理方式, 是基于引用计数的内存树(链), 如果把一个struct json_object 对象a, add到另一个对象b上, 就不用显式的释放(json_object_put) a了, 相当于把a挂到了b的对象树上, 释放b的时候, 就会释放a. 当a即add到b上, 又add到对象c上时会导致a被释放两次(double free), 这时可以增加a的引用计数(调用函数json_object_get(a)), 这时如果先释放b, 后释放c, 当释放b时, 并不会真正的释放a, 而是减少a的引用计数为1, 然后释放c时, 才真正释放a.

如果理解了这些, 使用jsonc库, 基本就不会有什么问题了.



http://gcoder.blogbus.com/logs/29975163.html
zz_d 2012-08-21
  • 打赏
  • 举报
回复
上面的回复排版不好, 再发下.

1. posturl 值,
为 "/falconconsole/server.php" 变为 "/falconconsoke/server.php",
为 "/falconconsle/server.php" 变为 "/falconconsld/server.php"
-- 第 12 个 字符的值减1


2. 设置 watch *(long *)(g_config->host_info.posturl+12),在 json_object_put()时变化
Hardware watchpoint 8: *(long *)(g_config->host_info.posturl+12)
Old value = 1702047589
New value = 1702047588
json_object_put (jso=0x8056930) at json_object.c:142
142 if(!jso->_ref_count) jso->_delete(jso);


json_object.c 中 json_object_put()的代码为
extern void json_object_put(struct json_object *jso)
{
if(jso) {
jso->_ref_count--;
if(!jso->_ref_count) jso->_delete(jso);
}
}


推测 jso->_ref_count地址和 g_config->host_info.posturl 指向地址有重合;
但是 g_config->host_info.posturl 的值也改变了.

3.当将 g_config->host_info.posturl 设为 "/falconconsolefalconconsolefalconconsole/sever.php"为
一个较长的值时, 调用 json_object_put() 后 posturl 也不改变;

4.posturl 指向的空间是通过malloc 分配, strncpy 字符串内容设定值的.


是否可能是系统内存分配导致的问题?
zz_d 2012-08-21
  • 打赏
  • 举报
回复

2. 设置 watch *(long *)(g_config->host_info.posturl+12)
在 json_object_put()时变化
Hardware watchpoint 8: *(long *)(g_config->host_info.posturl+12)

Old value = 1702047589
New value = 1702047588
json_object_put (jso=0x8056930) at json_object.c:142
142 if(!jso->_ref_count) jso->_delete(jso);
json_object.c 中 json_object_put()的代码为

extern void json_object_put(struct json_object *jso)
{
if(jso) {
jso->_ref_count--;
if(!jso->_ref_count) jso->_delete(jso);
}
}

// 推测 jso->_ref_count地址和 g_config->host_info.posturl 指向地址有重合;
// 但是 g_config->host_info.posturl 的值也改变了.
//

3. 当将 g_config->host_info.posturl 设为 "/falconconsolefalconconsolefalconconsole/sever.php"为
一个较长的值时, 调用 json_object_put() 后 posturl 也不改变;

4. posturl 指向的空间是通过 malloc 分配, strncpy 字符串内容设定值的.

是否可能是系统内存分配导致的问题?
zz_d 2012-08-21
  • 打赏
  • 举报
回复
添加 watch g_config->host_info.posturl 也监测不到值的变化.
ForestDB 2012-08-21
  • 打赏
  • 举报
回复
可以step into,这样更细点,看哪个操做touch到的。
ForestDB 2012-08-20
  • 打赏
  • 举报
回复
这就是为什么不要乱用全局变量。

69,382

社区成员

发帖
与我相关
我的任务
社区描述
C语言相关问题讨论
社区管理员
  • C语言
  • 花神庙码农
  • 架构师李肯
加入社区
  • 近7日
  • 近30日
  • 至今
社区公告
暂无公告

试试用AI创作助手写篇文章吧