前段时间开发的一个后端C模块上线后,线上出core,初始时,因为訪问压力不大,所以崩溃是上线3天左右出现的。当时用gdb跟进调用堆栈并检查源代码,发现出core位置的代码沒有啥问题。因为当时开发任务较重,且该模块不保存状态(崩溃重新启动不影响对外服务),所以沒有深入跟进。后来随着client版本号逐渐放量导致訪问压力上升,噩梦開始了。。。
该模块会不定时core掉,并且差点儿每次崩溃时的调用堆栈都不一样,关键是最后几层堆栈非常多都位于差点儿不可能出问题的代码中,比方库函数或厂里的公共库。
好在在众多core文件里发现规律:每次基本都是在对内存动态操作时挂掉,比方malloc/realloc/free/new/delete都引起了崩溃。并且幸运的是,崩溃进程还是输出了一些关键信息,比方以下这些(这些是在不同的崩溃时刻分别输出的):
*** glibc detected *** malloc(): memory corruption: 0x0000002a95c1ff10 ***
*** glibc detected *** double free or corruption (out): 0x0000000000f0d910 ***
*** glibc detected *** free(): invalid next size (normal): 0x0000002a96103b00 ***
*** glibc detected *** free(): invalid next size (fast): 0x0000000000f349d0 ***
*** glibc detected *** corrupted double-linked list: 0x0000002a95f062e0 ***
从上面的日志也能够看到,每次引起崩溃的直接原因都可能不同。用gdb又细致查看core文件发现,有时进程是收到SIGABRT信号后退出,有时又是收到SIGSEGV信号后退出。
由此,基本定位了崩溃原因:内存訪问越界导致破坏了heap的数据结构。用valgrind在线下环境启动进程,试图重现崩溃或定位越界訪问的代码,遗憾的是,脚本压了1个小时也没出现崩溃,而valgrind的输出报告也沒有越界代码位置的提示。
终于,细致检查源代码后发现,在某个回调函数中,new出来的buffer接收完通过http post方式发送过来的2进制数据后,我又多写了1行代码,相似于:recv_buf[data_len] = '\0',导致越界多写1个字节,终于引起各种莫名其妙的内存崩溃。
经验教训:
1)调用堆栈信息对定位问题帮助非常大,但也不可尽信。比方这次遇到的情况,每次出core的调用堆栈差点儿都不一样,并且最后几层栈帧都是不可能出现故障的库函数或久经考验的公司公共库,这样的情况下,思维须要跳出局部,在更高的层次寻找规律或原因
2)一旦定位崩溃属于堆内存读写越界问题,就细致检查自己的代码吧,因为库函数或公共库出问题的概率太小了,所以不要存在侥幸心理,这个时候,盲目的自信要不得
3)本来自觉得对内存操作已经非常小心了,没想到还是在想当然的瞬间写下犯错的代码,导致终于花费非常多时间和精力去“捉虫”。只是好在跟进崩溃的过程中添加了一点分析/定位问题的经验,也算有些收获吧

=============== EOF =================

最新文章

  1. ubuntu 彻底卸载软件
  2. [No00002A]26个英语字母的原始象形意义、含义、产生及发展历史
  3. 71-IO 流
  4. CE搜索内存数据的原理
  5. nginx 重写 rewrite 基础及实例
  6. spring da-y02-go1
  7. 也用 Log4Net 之将日志记录到数据库的配置 (一)
  8. iOS开发UI篇——九宫格坐标计算
  9. centos7安装httpd和php
  10. Winform DevExpress控件库(二) 使用SplashScreenManager控件定制程序加载页面
  11. JDK源码分析(7)String
  12. Docker应用:Hello World
  13. 胡同门牌号-2015决赛Java语言A组第一题
  14. OpenCV——图像的载入、显示、输出到文件和滑动条、鼠标操作
  15. Java 内存模型 ,一篇就够了!
  16. 【代码审计】iZhanCMS_v2.1 后台存在多个SQL注入漏洞分析
  17. 【Asp.net入门3-02】使用jQuery-jQuery 入门
  18. linux下启动tomcat服务的命令是什么
  19. NetCore 下集成SignalR并进行分组处理
  20. 136. Single Number唯一的数字

热门文章

  1. 已加载“C:\Windows\SysWOW64\ntdll.dll”。无法查找或打开 PDB 文件。
  2. automaticallyAdjustsScrollViewInsets(UITextView文字顶部留有空白)
  3. MQTT--入门 续
  4. Linux中的一个命令行计算器bc简介
  5. MyEclipse配置输出控制台信息至文本文件里
  6. linux下拷贝隐藏文件
  7. 解决myeclipse10.x的Servers产生的at com.genuitec.eclipse.ast.deploy.core.Deployment.<init>(Unknown Source)错
  8. 【Navicat Premium】之连接Oracle数据库
  9. 【Mysql】Navicat For Mysql快捷键
  10. Mysql----MySQL的mysql_insert_id和LAST_INSERT_ID(转)