记录一次内存错误排查过程
程序员文章站
2022-07-15 07:58:32
...
问题现象
一个播放器的实现代码,在多次播放后,出现异常挂死,gdb显示如下图
通过bt命令查看函数调用栈,只有一条有效消息,就是 “#3 0xa0” 这个地址明显是错误的。所有怀疑是栈被破坏了。
直接报错内容也是多种多样。以下这些错误都出现过。
double free or corruption (!prev)
corrupted size vs. prev_size
double free or corruption (out)
malloc(): memory corruption (fast)
double free or corruption (fasttop)
glibc detected *** free(): invalid next size (normal)
定位过程
- 根据log信息或者注释部分代码的方式来收敛错误范围。
- 打印关键变量地址,复现问题,进一步所有排查范围。
- 经过仔细核对关键变量地址的变化,定位到面代码。
- 前后地址不一致,中间部分代码又跟被修改变量不相关。
- 仔细检查链表操作代码,没有问题。
- 然后根据这部分里面其他函数调用,及相关逻辑进行检查,发现player播放完成后任务被销毁,但是没有从链表中删除任务节点。
- 修正之后,再没有出现问题。
总结
- 通过最开始报的各种错误集gdb看到的调用栈中异常地址,大致判断是栈被破坏或者出现使用野指针的问题。所以内存使用就乱了,关于内存报错的信息也是千奇百怪。
- 关于内存错误的问题,多数是内存地址被踩,可以根据关键变量地址被修改来缩小查找范围。当然,如果只有log,没有条件去重新运行复现问题,就只能推测,仔细检查代码。
推荐阅读