现象:
开发过程中遇到一个可以重现的奇怪的 bug,即注册用户后,第3方登录时服务器崩溃。
下面附上日志和说明
-
[ns__MobileRegister:1360] malloc 0x7f587000ef80 // 注册时分配一个 user 结构体,其地址远高于程序刚启动时分配的4字节地址。但这不是bug,因为系统是64位的 centos7。
-
[ns__MonUserLoginMc:2767] User [test_13641489180] logged // 用户登录,返回sess。
-
[ns__AuthTelSession:3987] Tel=13641489185, sess=M9xMzku1TOyZSZsYV6mOZ7RAPfczHkI // 第3方使用 tel+sess 登录
-
[cmpSess:3967] test: 0x25f3f10 // 遍历用户树时打印出地址。为什么要遍历呢,因为第3方不是使用用户名(主键)登录。
-
...
-
[cmpSess:3967] test: 0x259f780
-
[cmpSess:3965] hit 0x7f587000ef80 // 找到需要的用户。打印其地址:虽然长得另类,但很快我就打消疑虑。注册时 malloc 确实分配了这个么“另类”。
-
[cuindex_by_sess:3979] sz=8, puser 0x7000ef80 //
-
// crash when access user !!!
惊讶吧,竟然在找到用户后崩溃了!
原因很明显,返回的地址不正确啊。
为什么为会不正确呢?
先看代码
-
====================================
-
// file1.c
-
-
-
int cmpSess(void *cu_node,void *param)
-
{
-
user_desc_t *cu_desc = (user_desc_t*)cu_node;
-
char *sess = param;
-
int res = strcmp(sess, cu_desc->loginsession);
-
if(res == 0){
-
dprintf(WARN, 0, "hit %p", cu_node);
-
} else {
-
dprintf(WARN, 0, "test: %p", cu_node);
-
}
-
return res;
-
}
-
-
-
void * cuindex_by_sess(char *sess)
-
{
-
struct rb_root *cu_tree = &g_sysconfig.cu_tree;
-
void* res = rbtree_index(cu_tree, (void *)sess, cmpSess); //
-
dprintf(WARN, 0, "sz=%d, puser %p", sizeof(res), res); //
-
return res;
-
}
-
====================================
-
// file2.c
-
-
-
typedef int (* rbindex_comparator)(void *,void *);
-
-
-
void* rbtree_index(struct rb_root* root, void *param, rbindex_comparator item_handle)
-
{
-
struct rb_node* node;
-
rbtree_item_t* item;
-
-
-
for (node = rb_first (root); node; node = rb_next (node))
-
{
-
item = rb_entry (node, rbtree_item_t, node);
-
if(item_handle(item->data,param) == 0){
-
printf ("==>[Item:%p,key:%#lx,data:%p]\n", item,item->key,item->data);
-
return item->data;
-
}
-
}
-
return NULL;
-
}
以我多年的C语言功力,认为这代码没有问题!
可怎么就在返回时把指针的高位丢了呢,邪门!
可能是我装的h2数据库搞鬼 -- 命令行提示符变成h2的图标了。中文输入法在debug过程中输出乱码不能用了。邪门!
卸载h2,重启电脑。
尝试N次,依旧崩溃。
好嚣张的bug! -_-!!!
百思不得姐,那就找谷哥吧。
Bing 搜索 centos function return 64bit pointer 即可找到答案。
http://www.cnblogs.com/europelee/p/4626700.html
回头找到编译输出信息:
-
test1.c: 在函数‘cuindex_by_sess’中:
-
test1.c:3978:14: 警告:初始化时将整数赋给指针,未作类型转换 [默认启用]
-
void* res = rbtree_index(cu_tree, (void *)sess, cmpSess)
明明定义的指针,为什么编译器说“整数”呢?
由于没有在头文件中对 rbtree_index 函数进行声明,编译器将函数返回值当成整数处理了!
从不轻易怀疑千锤百炼的 gcc 编译器。
但我没有认真对待它给出的警告。
我选择了无视,于是服务器崩溃了!
代码世界容不得一点马虎。
要严谨呢,赶快把堆积的编译警告消除!
阅读(960) | 评论(0) | 转发(0) |