简介


最近的应用程序遇到了点问题,它总是在退出的时候段错误崩溃。

段错误大家应该不陌生了,内存使用不当导致段错误。

通过尝试gdb core文件,dmesg,objdump库文件等方法终于定位到了崩溃原因。

这里作一记录。

gdb无效时使用dmesg调试


我打开了coredump配置:

在运行进程的终端执行:ulimit -c unlimited,该方法只能临时打开当前终端的内核转储,详细方法请参考:内核转储-coredump简介

程序崩溃时产生了core文件,但是gdb打印的情况如下:

Program terminated with signal SIGSEGV, Segmentation fault.
#0  0x00007eff6effd9fd in ?? ()
[Current thread is 1 (LWP 19887)]
(gdb) bt
#0  0x00007eff6effd9fd in ?? ()
#1  0x000055e3e8345330 in ?? ()
#2  0x635027382a97e600 in ?? ()
#3  0x000055e3e8343f60 in ?? ()
#4  0x000055e3e7a99f67 in ?? ()
#5  0x000055e3e8345100 in ?? ()
#6  0x635027382a97e600 in ?? ()
#7  0x000055e3e8345100 in ?? ()
#8  0x00007ffcd31007e0 in ?? ()
#9  0x0000000000000000 in ?? ()
(gdb)

这就尴尬了。我编译程序时加了-g呀,怎么是这样呢?

经查,出现这种情况可能是在编译时加了-O2选项,或者是程序链接的库没有-g编译。

没办法,由于当时机器上没有源码,只能进一步查查原因。

coredump行不通了,还有个dmesg。一般异常崩溃的程序,内核都会在日志里记录一下崩溃信息,直接在终端运行dmesg查看即可。

关于dmesg的更多介绍,请参考Linux内核日志查看之dmesg命令简介。

刚崩溃时查看的话,最后一行应该就是。我的显示如下:

[1745123.819693] godserver[29078]: segfault at 1ff8 ip 00007ff3736949fd sp 00007fff9f148ba0 error 4 in libc-2.27.so[7ff3735fd000+1e7000]

其中,

  • 第一列为时间戳,使用dmesg -T可显示人类时间

  • 二列为进程名和进程id

  • 后面的3个奇葩数字分别为出错时的地址(用处不大)、发生错误时指令的地址、堆栈指针

  • error number为4,意思是用户态程序内存读出错,error 由三个bit位组成,它的具体含义如下:

    • bit2: 值为1表示是用户态程序内存访问越界,值为0表示是内核态程序内存访问越界
    • bit1: 值为1表示是写操作导致内存访问越界,值为0表示是读操作导致内存访问越界
    • bit0: 值为1表示没有足够的权限访问非法地址的内容,值为0表示访问的非法地址根本没有对应的页面,也就是无效地址
  • 后面是崩溃的具体位置,发生在libc-2.27.so库内,libc在此程序中映射的内存基址为7ff3735fd000

  • 注意一点,新手可能会怀疑是不是库函数有问题啊?这个其实不用担心,遇到这种情况,99.9999999999%的可能性是自己的程序有问题。如果你真的发现库的问题,可以提交issue去了。

到这里,可以先分析一下,哪些操作会导致内存读崩溃:

  • 操作null指针
  • 把未初始化或非法指针交给函数处理
  • 读内存越界
  • 读取非法内存

这样范围很大,不可能一点一点看代码找吧。。。

其实,根据现有的信息,我们还是可以再做些努力的。

那就从libc入手吧。注意两个地址:

  • 崩溃时指令地址ip:00007ff3736949fd
  • 崩溃库的基地址:7ff3735fd000

两者相减,其实就得到了崩溃时库的位置:9 79FD。

下面我们来看一下相对代码段地址为979FD的地方是什么函数:

# -t为打印文件的符号表入口,具体可查看man page
# -T为打印文件的动态符号表入口
% objdump -tT /lib/x86_64-linux-gnu/libc.so.6 | grep 979
00000000000979c0 g    DF .text  0000000000000e31 (GLIBC_2.2.5) cfree
00000000000979c0 g    DF .text  0000000000000e31  GLIBC_2.2.5 __libc_free
00000000000979c0 g    DF .text  0000000000000e31  GLIBC_2.2.5 free

打印出来的函数是free。

结合之前的分析,读内存非法,调用free确实可能导致这个崩溃。很可能是free了非法的地址,即free了一个无效的指针。

到这里,为了验证一下自己的猜想,可以写个free无效指针的测试程序,运行一下,看看它是不是也会导致dmesg记录这样一条日志。

c++中可以导致底层free的函数也不多,如free,delete, 智能指针的析构等。可以重点查一下它们。

经过添加日志等方式定位,我的程序是在退出时,一个类析构时free了无效的指针。

使用gdb如虎添翼


得空的时候,我导入了一份源码,加上-g,去掉-O2编译扔上去,崩溃,就可以gdb看看了。

还没等到我gdb,程序崩溃时就输出了一堆东西:

*** Error in `./godserver': free(): invalid pointer: 0x00007ffeb5a483d0 ***
======= Backtrace: =========
/lib64/libc.so.6(+0x81299)[0x7fe119d7e299]
./godserver[0x43599a]
./godserver[0x43591d]
./godserver[0x4a2d79]
./godserver[0x4a2df9]
./godserver[0x445d4b]
./godserver[0x43ffe3]
/lib64/libc.so.6(+0x39ce9)[0x7fe119d36ce9]
/lib64/libc.so.6(+0x39d37)[0x7fe119d36d37]
/lib64/libc.so.6(__libc_start_main+0xfc)[0x7fe119d1f55c]
./godserver[0x4190d7]
======= Memory map: ========
00400000-005ea000 r-xp 00000000 fd:02 57716                              /home/ysj/work/godserver
007e9000-007ef000 r--p 001e9000 fd:02 57716                              /home/ysj/work/godserver
007ef000-007f0000 rw-p 001ef000 fd:02 57716                              /home/ysj/work/godserver
007f0000-007f1000 rw-p 00000000 00:00 0
00f0d000-1491ad000 rw-p 00000000 00:00 0                                 [heap]
7fddd0000000-7fddd737b000 rw-p 00000000 00:00 0
7fddd737b000-7fddd8000000 ---p 00000000 00:00 0
7fddd8000000-7fdde0000000 rw-p 00000000 00:00 0
7fdde0000000-7fdde8000000 rw-p 00000000 00:00 0
7fdde8000000-7fddec000000 rw-p 00000000 00:00 0
# 后面省略

可以看出,是free了无效的指针,哈哈。

接着上gdb:

gdb exe_file core_file

执行bt,就可以看出是具体是哪行代码搞的了,分分钟解决bug。

小节


对于开发中的程序,编译时加-g,这样出错之后好定位解决问题。

注意-g和-O2不要同时使用,既然要调试,就先不要优化啦。

在没有调试条件时,使用内核提供的信息也可以看出个大概,这样心里有数,不至于慌。

参考

Linux内核日志查看之dmesg命令简介
内核转储-coredump简介
一次segfault错误的排查过程

从libc-2.27.so[7ff3735fd000+1e7000]崩溃回溯程序段错误segfault相关推荐

  1. 从libc-2.27.so[7fd68b298000+1e7000]崩溃回溯程序段错误segfault

    近期在外场试验过程中出现了一次进程退出的问题(在西安地面测试中也出现过一次),但是因为该问题不复现,后面就一直记着但没有进行闭环,也不清楚是异常退出还是因为资源消耗问题被系统杀死.这次回来之后有必要进 ...

  2. 通过崩溃地址找错误行数之Delphi版

    通过崩溃地址找错误行数之Delphi版 2009-5-11 17:42:35 来源: 转载 作者:网络 访问:360 次 被顶:2 次 字号:[大 中 小] 核心提示:什么是 MAP 文件?简单地讲, ...

  3. 未能找到程序集“platform.winmd_应用程序崩溃后 微软错误报告工具到底是如何联机检查解决方案的?...

    在 Windows 应用意外崩溃后,系统似乎会努力地寻找解决方案.但是在绝大多数情况下,这一切都是徒劳的,并不会向用户给出任何结果.即便如此,很多人还是想要知道这个无效的过程期间到底都发生了什么.好消 ...

  4. libc.so.6 导致Linux系统崩溃

    问题 由于缺少对libc.so的认识,以为跟普通的lib包类似,直接把高版本的so软连过去就可以满足安装和升级,造成错误操作直接导致Linux系统崩溃. 错误操作: 在root用户下将/usr/lib ...

  5. 如何看待2018年6月27日阿里云崩溃?

    小和尚的庙里住进了一位女施主. 小和尚吓坏了,逃去殿里敲木鱼.山下的女人是老虎,现在老虎居然住进庙里了,看来自己和师父是要被吃了. 女施主闲暇无事,也走到殿里,看见一位小师父红着脸拼命敲木鱼,好奇地过 ...

  6. Android中处理崩溃闪退错误

    我们需要的是软件有一个全局的异常捕获器,当出现一个我们没有发现的异常时,捕获这个异常,并且将异常信息记录下来,上传到服务器公开发这分析出现异常的具体原因.不过首先我们还是来了解以下两个类:androi ...

  7. Linux 2.6.32-279.el6.x86_64 ANDROID SDK碰到”LIBC.SO.6: VERSION `GLIBC_2.14′ NOT FOUND”的解决方法(1)

    1.执行locate libc.so.6找到库的位置;      /lib64/libc.so.6 2.查看系统已支持的版本: strings /lib64/libc.so.6 | grep GLIB ...

  8. jvm崩溃的原因_JVM崩溃时:如何调查最严重错误的根本原因

    jvm崩溃的原因 当应用程序崩溃时,您可以学到什么? 我认为,"后见之明是20 /"是最喜欢的短语之一托马斯·罗梅尔 ,工程ZeroTurnaround的副总裁. 好吧,我实际上不 ...

  9. JVM崩溃时:如何调查最严重错误的根本原因

    当应用程序崩溃时,您可以学到什么? 我认为,"后见之明是20 /"是最喜欢的短语之一托马斯·罗梅尔 ,工程ZeroTurnaround的副总裁. 好吧,我实际上不确定在他的短语中占 ...

最新文章

  1. UWP入门(二) -- 基础笔记
  2. 安装和规划邮件服务器
  3. Javascript获取url参数值
  4. 记录从前端到后端--博客项目
  5. Java和.NET(C#)的开发用到的技术对比总结
  6. 二级指针与指针数组的关系
  7. linux 选择文件指定的行数据类型,06练习题
  8. 针对不同pandas版本进行列名的修改
  9. Jboss EAP:native management API学习
  10. linux查看设备网卡型号,linux查看网卡型号
  11. 怎么把两个pdf合并成一个?pdf合并方法
  12. 【C++】:动态库与静态库区别
  13. 送一首诗给心急的、望子成龙的父母们——《牵一只蜗牛去散步》
  14. 软件工程项目分析(四) 瀚海星云新版网站 By 郭家华
  15. 中式红木装修——打造适合审美的居住空间
  16. aptx android8,支持aptxHD和LDAC!安卓8.0蓝牙音质大爆发
  17. 基于STM32F103单片机的智能扫地机器人 循迹避障车 原理图PCB设计
  18. Leo写的前言 自由与规则—— 程序员羊皮卷 连载 8
  19. 如何用c语言计算三角形面积
  20. Python爬取新浪新闻评论的url查找方法

热门文章

  1. python多线程tomorrow的使用
  2. 从无秘和知乎看中国社交产品的特点
  3. js中的reduce函数详细解释
  4. 用宅购节当前哨战,京东到家为双十一暗中蓄力
  5. 阿蒙森 斯科特_三个斯科特的故事值得一听...
  6. deepspeech 2 (百度 2016 论文解读 )
  7. 李沐动手学深度学习笔记---含并行连结的网络 GoogLeNet / Inception V3
  8. python爬虫实战之爬取51job前程无忧简历
  9. 懂23种语言 2019年上市 宝马的AI助理有哪些不同!
  10. ISP算法介绍--------super Good