Chinaunix首页 | 论坛 | 博客
  • 博客访问: 1530783
  • 博文数量: 226
  • 博客积分: 3997
  • 博客等级: 少校
  • 技术积分: 2369
  • 用 户 组: 普通用户
  • 注册时间: 2010-06-19 17:26
个人简介

Never save something for a special occasion. Every day in your life is a special occasion.

文章分类

全部博文(226)

文章存档

2018年(5)

2017年(11)

2016年(1)

2015年(17)

2014年(14)

2013年(30)

2012年(5)

2011年(52)

2010年(107)

分类: C/C++

2018-04-20 21:53:22

现象:
开发过程中遇到一个可以重现的奇怪的 bug,即注册用户后,第3方登录时服务器崩溃。

下面附上日志和说明

点击(此处)折叠或打开

  1. [ns__MobileRegister:1360] malloc 0x7f587000ef80 // 注册时分配一个 user 结构体,其地址远高于程序刚启动时分配的4字节地址。但这不是bug,因为系统是64位的 centos7。
  2. [ns__MonUserLoginMc:2767] User [test_13641489180] logged // 用户登录,返回sess。
  3. [ns__AuthTelSession:3987] Tel=13641489185, sess=M9xMzku1TOyZSZsYV6mOZ7RAPfczHkI // 第3方使用 tel+sess 登录
  4. [cmpSess:3967] test: 0x25f3f10 // 遍历用户树时打印出地址。为什么要遍历呢,因为第3方不是使用用户名(主键)登录。
  5. ...
  6. [cmpSess:3967] test: 0x259f780
  7. [cmpSess:3965] hit 0x7f587000ef80 // 找到需要的用户。打印其地址:虽然长得另类,但很快我就打消疑虑。注册时 malloc 确实分配了这个么“另类”。
  8. [cuindex_by_sess:3979] sz=8, puser 0x7000ef80 //
  9. // crash when access user !!!

惊讶吧,竟然在找到用户后崩溃了!
原因很明显,返回的地址不正确啊。
为什么为会不正确呢?

先看代码


点击(此处)折叠或打开

  1. ====================================
  2. // file1.c


  3. int cmpSess(void *cu_node,void *param)
  4. {
  5.  user_desc_t *cu_desc = (user_desc_t*)cu_node;
  6.  char *sess = param;
  7.  int res = strcmp(sess, cu_desc->loginsession);
  8.  if(res == 0){
  9.  dprintf(WARN, 0, "hit %p", cu_node);
  10.  } else {
  11.  dprintf(WARN, 0, "test: %p", cu_node);
  12.  }
  13.  return res;
  14. }


  15. void * cuindex_by_sess(char *sess)
  16. {
  17.  struct rb_root *cu_tree = &g_sysconfig.cu_tree;
  18.  void* res = rbtree_index(cu_tree, (void *)sess, cmpSess); //
  19.  dprintf(WARN, 0, "sz=%d, puser %p", sizeof(res), res); //
  20.  return res;
  21. }

点击(此处)折叠或打开

  1. ====================================
  2. // file2.c


  3. typedef int (* rbindex_comparator)(void *,void *);


  4. void* rbtree_index(struct rb_root* root, void *param, rbindex_comparator item_handle)
  5. {
  6.  struct rb_node* node;
  7.  rbtree_item_t* item;


  8.  for (node = rb_first (root); node; node = rb_next (node))
  9.  {
  10.  item = rb_entry (node, rbtree_item_t, node);
  11.  if(item_handle(item->data,param) == 0){
  12.  printf ("==>[Item:%p,key:%#lx,data:%p]\n", item,item->key,item->data);
  13.  return item->data;
  14.  }
  15.  }
  16.  return NULL;
  17. }

以我多年的C语言功力,认为这代码没有问题!
可怎么就在返回时把指针的高位丢了呢,邪门!
可能是我装的h2数据库搞鬼 -- 命令行提示符变成h2的图标了。中文输入法在debug过程中输出乱码不能用了。邪门!
卸载h2,重启电脑。
尝试N次,依旧崩溃。
好嚣张的bug! -_-!!!

百思不得姐,那就找谷哥吧。
Bing 搜索 centos function return 64bit pointer 即可找到答案。
http://www.cnblogs.com/europelee/p/4626700.html



回头找到编译输出信息:

点击(此处)折叠或打开

  1. test1.c: 在函数‘cuindex_by_sess’中:
  2.  test1.c:3978:14: 警告:初始化时将整数赋给指针,未作类型转换 [默认启用]
  3.    void* res = rbtree_index(cu_tree, (void *)sess, cmpSess)

明明定义的指针,为什么编译器说“整数”呢?
由于没有在头文件中对 rbtree_index 函数进行声明,编译器将函数返回值当成整数处理了!

从不轻易怀疑千锤百炼的 gcc 编译器。
但我没有认真对待它给出的警告。
我选择了无视,于是服务器崩溃了!

代码世界容不得一点马虎。
要严谨呢,赶快把堆积的编译警告消除!

阅读(960) | 评论(0) | 转发(0) |
给主人留下些什么吧!~~