前段时间开发的一个后端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 =================

内存写越界导致破环堆结构引起的崩溃问题定位经验[如报错malloc(): memory corruption或free(): invalid next size]的更多相关文章

  1. 【JVM之内存与垃圾回收篇】堆

    堆 堆的核心概念 堆针对一个 JVM 进程来说是唯一的,也就是一个进程只有一个 JVM,但是进程包含多个线程,他们是共享同一堆空间的. 一个 JVM 实例只存在一个堆内存,堆也是 Java 内存管理的 ...

  2. 【CPU微架构设计】分布式多端口(4写2读)寄存器堆设计

    寄存器堆(Register File)是微处理的关键部件之一.寄存器堆往往具有多个读写端口,其中写端口往往与多个处理单元相对应.传统的方法是使用集中式寄存器堆,即一个集中式寄存器堆匹配N个处理单元.随 ...

  3. C++内存管理4-Windows编程中的堆管理(转)

    1 引言 在大多数Windows应用程序设计中,都几乎不可避免的要对内存进行操作和管理.在进行大尺寸内存的动态分配时尤其显的重要.本文即主要对内存管理中的堆管理技术进行论述. 堆(Heap)实际是位于 ...

  4. Leetcode Lect3 内存中的栈空间与堆空间

    内存中的栈空间与堆空间 我们通常所说的内存空间,包含了两个部分:栈空间(Stack space)和堆空间(Heap space) 当一个程序在执行的时候,操作系统为了让进程可以使用一些固定的不被其他进 ...

  5. 【pwn】学pwn日记(堆结构学习)

    [pwn]学pwn日记(堆结构学习) 1.什么是堆? 堆是下图中绿色的部分,而它上面的橙色部分则是堆管理器 我们都知道栈的从高内存向低内存扩展的,而堆是相反的,它是由低内存向高内存扩展的 堆管理器的作 ...

  6. Android内存机制分析1——了解Android堆和栈

    //----------------------------------------------------------------------------------- Android内存机制分析1 ...

  7. 堆结构的优秀实现类----PriorityQueue优先队列

    之前的文章中,我们有介绍过动态数组ArrayList,双向队列LinkedList,键值对集合HashMap,树集TreeMap.他们都各自有各自的优点,ArrayList动态扩容,数组实现查询非常快 ...

  8. RocketMQ_问题_启动报错,修改堆内存大小

    1.启动broker报错 虚拟机内存小,导致虚拟机中的JVM内存小,进而在启动broker时分配JVM内存遇到问题 查询网上得知,查看/usr/local/rocketmq-all-4.3.0/dis ...

  9. Libheap:一款用于分析Glibc堆结构的GDB调试工具

    Libheap是一个用于在Linux平台上分析glibc堆结构的GDB调试脚本,使用Python语言编写.         安装 Glibc安装 尽管Libheap不要求glibc使用GDB调试支持和 ...

随机推荐

  1. Linux非阻塞IO(三)非阻塞IO中缓冲区Buffer的实现

    本文我们来实现回射服务器的Buffer.   Buffer的实现   上节提到了非阻塞IO必须具备Buffer.再次将Buffer的设计描述一下: 这里必须补充一点,writeIndex指向空闲空间的 ...

  2. 嵌套矩形——DAG上的动态规划

    有向无环图(DAG,Directed Acyclic Graph)上的动态规划是学习动态规划的基础.非常多问题都能够转化为DAG上的最长路.最短路或路径计数问题. 题目描写叙述: 有n个矩形,每一个矩 ...

  3. hadoop:WordCount问题总结

    今天玩了一下hadoop的MapReduce,中途遇到了几个问题,在此记录一下. 1.一切按照配置完成之后,hadoop namenode format,start-all.sh启动,使用jps查看进 ...

  4. 使用 JavaScript开发的跨平台音乐、书籍播放器

    代码地址如下:http://www.demodashi.com/demo/12542.html 演示效果 歌曲推荐界面 歌手搜索界面 歌词预览界面 书籍推荐界面 代码实现过程 首页代码: 'use s ...

  5. Android插件化开发,初入殿堂

    好久没有写博客了,这次准备写写我这几天的研究成果--Android插件化开发框架CJFrameForAndroid. 好久没有写博客了,这次准备写写我这几天的研究成果--Android插件化开发框架C ...

  6. <转>Windows平台下Makefile学习笔记(二)

    本文转自:http://blog.csdn.net/clever101/article/details/8286066 上次我们学习了怎么用Makefile编译一个控制台工程.这次我们学习一下如何使用 ...

  7. webAPI 405

    web.config 配置 <system.webServer> <modules> <remove name="WebDAVModule" /> ...

  8. IPython introduction

    转载:http://blog.csdn.net/gavin_john/article/details/53086766 1. IPython介绍 ipython是一个python的交互式shell,比 ...

  9. freemarker 开始时间与当前时间进行比较

    <#if startTime?datetime lt .now?datetime>:年月日时分秒比较 <#if startTime?date lt .now?date>:年月日 ...

  10. (转) 对svn分支合并类型和深度的理解

    合并的工作是把主干或者分支上合并范围内的所有改动列出,并对比当前工作副本的内容,由合并者手工修改冲突,然后提交到服务器的相应目录里.如果当前工作副本是主干,则合并的范围是分支上的改动,如果工作副本是分 ...