- 论坛徽章:
- 1
|
本帖最后由 robin10 于 2013-03-26 06:19 编辑
[1楼已经重新编辑。 为了减少干扰,把其他有干扰的信息也尽量去除]
原标题:
有 没有 可 能 是 malloc() 的 问题?
这是一个很狗血的BUG。
花费了3,4天的时间
原因是在64bit的系统上,隐式返回的指针默认是32bit的,当返回的指针值(应该其他数字也应该如此或者类似)大于32bit时,
系统会根据返回值的最高位补齐到64位,而补齐部分,将根据返回值的最高位不同而不同。
据说是这样的(以下内容为揣测,只为了说明道理,不代表正确,仅供参考):
1.如果最高位是0,则补0,即如果返回值为 0111 1111 1111 1111 1111 1111 1111 11111B, 则补齐后为 0x0000 0000 efff ffff;
2.如果最高位是1,则补1,即如果返回值为 1011 1111 1111 1111 1111 1111 1111 11111B, 则补齐后为 0xffff ffff bfff ffff;
于是就有,当返回的指针值不大于32bit时, 程序正常运作;当返回值大于32bit时(并且最高位为1),系统补齐的高位为1,于是就得到了一个无效地址。。。
由于之前一直在ARM上工作,根本就不会遇到这种问题,对这方面一点概念都没有。
其实,这种隐式声明,在编译时 -Wall 参数会有警告。
按照习惯,所有的Warning最终自己都会清除。
只是在开始调试功能阶段,往往会先忽略这些warning. 这也是悲剧的根源!
而刚好,found_bakup_msg_node() 是前几天才添加的,还没有在头文件中声明,于是调用的时候变成了隐式声明调用的。 (不能偷懒啊。。。)
在头文件中添加对 found_bakup_msg_node()的声明,并在调用函数中包含该头文件以后,
目前运行良好,30次的测试,还没见到之前的SEG FAULT。 之前一般在测试5次左右就会出现一次。
希望这点教训,可以给自己和后来者一点好处!
再次谢谢所有给意见的XDJM!
这方面更加详细的描述,请参考:
http://blogs.360.cn/360apps/2013 ... %E5%A3%B0%E6%98%8E/
http://bbs.chinaunix.net/thread-3755898-1-1.html
--------------------------------------------------------------------------------------------------------------------
代码的主要功能是
1. found_bakup_msg_node() malloc一个 struct MSG_INFO 空间,然后把地址返回给调用函数。
2.调用found_bakup_msg_node() 的函数把内容拷贝到malloc得到的空间。
从LOG上来看,
在found_bakup_msg_node() 中打印的指针值 0x7f6090032f70,和调用该API的函数内部打印得到的指针值0xffffffff90032f70 不同(后8位相同)。
从值上看,应该是一个无效地址0xffffffff90032f70,(机器上8G空间)于是,往这个地址上写数据的时候,就出现了Segmentation fault.
------------------------------------ source code------------------------------------------------------------
{
.....
.....
pMsg_next = header;
while(pMsg_next != NULL) {
pMsg_node = found_bakup_msg_node();
if(pMsg_node != NULL) {
Dprintf("#%s#%d %p\n", __FUNCTION__, __LINE__, pMsg_node);
.....
}
}
return ;
}
===================================================================
struct MSG_INFO* found_bakup_msg_node(void)
{
struct MSG_INFO* msg_node = NULL;
msg_node = (struct MSG_INFO*)malloc(sizeof(struct MSG_INFO));
Dprintf("#%s#%d %p\n", __FUNCTION__, __LINE__, msg_node);
if(msg_node != NULL) {
memset(msg_node, 0x0, sizeof(struct MSG_INFO));
//should use calloc()
}
return msg_node;
}
--------------------------------------------------LOG--------------------------------
#cp_msg_list#552 count = 0, header=0x923950
#found_bakup_msg_node#alloc_bakup_count=1 0x7f6090032f70 //malloc() 返回值
#cp_msg_list#561 0xffffffff90032f70 //接收到的指针
Segmentation fault
#
# |
|