了解如何处理转储文件将帮你找到应用中难以重现的 bug。

• 来源:linux.cn • 作者:Stephan Avenwedde • 译者:Xingyu.Wang •

(本文字数:5501,阅读时长大约:6 分钟)

崩溃转储、内存转储、核心转储、系统转储……这些全都会产生同样的产物:一个包含了当应用崩溃时,在那个特定时刻应用的内存状态的文件。

这是一篇指导文章,你可以通过克隆示例的应用仓库来跟随学习:

git clone https://github.com/hANSIc99/core_dump_example.git

信号如何关联到转储

信号是操作系统和用户应用之间的进程间通讯。Linux 使用 POSIX 标准 中定义的信号。在你的系统上,你可以在 /usr/include/bits/signum-generic.h 找到标准信号的定义。如果你想知道更多关于在你的应用程序中使用信号的信息,这有一个信息丰富的 signal 手册页 。简单地说,Linux 基于预期的或意外的信号来触发进一步的活动。

当你退出一个正在运行的应用程序时,应用程序通常会收到 SIGTERM 信号。因为这种类型的退出信号是预期的,所以这个操作不会创建一个内存转储。

以下信号将导致创建一个转储文件(来源: GNU C库 ):

  • SIGFPE:错误的算术操作
  • SIGILL:非法指令
  • SIGSEGV:对存储的无效访问
  • SIGBUS:总线错误
  • SIGABRT:程序检测到的错误,并通过调用 abort() 来报告
  • SIGIOT:这个信号在 Fedora 上已经过时,过去在 PDP-11 上用 abort() 时触发,现在映射到 SIGABRT

创建转储文件

导航到 core_dump_example 目录,运行 make,并使用 -c1 开关执行该示例二进制:

./coredump -c1

该应用将以状态 4 退出,带有如下错误:

Dump written

“Abgebrochen (Speicherabzug geschrieben) ”(LCTT 译注:这是德语,应该是因为本文作者系统是德语环境)大致翻译为“分段故障(核心转储)”。

是否创建核心转储是由运行该进程的用户的资源限制决定的。你可以用 ulimit 命令修改资源限制。

检查当前创建核心转储的设置:

ulimit -c

如果它输出 unlimited,那么它使用的是(建议的)默认值。否则,用以下方法纠正限制:

ulimit -c unlimited

要禁用创建核心转储,可以设置其大小为 0:

ulimit -c 0

这个数字指定了核心转储文件的大小,单位是块。

什么是核心转储?

内核处理核心转储的方式定义在:

/proc/sys/kernel/core_pattern

我运行的是 Fedora 31,在我的系统上,该文件包含的内容是:

/usr/lib/systemd/systemd-coredump %P %u %g %s %t %c %h

这表明核心转储被转发到 systemd-coredump 工具。在不同的 Linux 发行版中,core_pattern 的内容会有很大的不同。当使用 systemd-coredump 时,转储文件被压缩保存在 /var/lib/systemd/coredump 下。你不需要直接接触这些文件,你可以使用 coredumpctl。比如说:

coredumpctl list

会显示系统中保存的所有可用的转储文件。

使用 coredumpctl dump,你可以从最后保存的转储文件中检索信息:

[stephan@localhost core_dump_example]$ ./coredump Application started…(…….)Message: Process 4598 (coredump) of user 1000 dumped core.Stack trace of thread 4598:#0 0x00007f4bbaf22625 __GI_raise (libc.so.6)#1 0x00007f4bbaf0b8d9 __GI_abort (libc.so.6)#2 0x00007f4bbaf664af __libc_message (libc.so.6)#3 0x00007f4bbaf6da9c malloc_printerr (libc.so.6)#4 0x00007f4bbaf6f49c _int_free (libc.so.6)#5 0x000000000040120e n/a (/home/stephan/Dokumente/core_dump_example/coredump)#6 0x00000000004013b1 n/a (/home/stephan/Dokumente/core_dump_example/coredump)#7 0x00007f4bbaf0d1a3 __libc_start_main (libc.so.6)#8 0x000000000040113e n/a (/home/stephan/Dokumente/core_dump_example/coredump)Refusing to dump core to tty (use shell redirection or specify — output).

这表明该进程被 SIGABRT 停止。这个视图中的堆栈跟踪不是很详细,因为它不包括函数名。然而,使用 coredumpctl debug,你可以简单地用调试器(默认为 GDB )打开转储文件。输入 bt( 回溯(backtrace)的缩写)可以得到更详细的视图:

Core was generated by `./coredump -c1'.Program terminated with signal SIGABRT, Aborted.#0  __GI_raise (sig=sig@entry=6) at ../sysdeps/unix/sysv/linux/raise.c:5050  return ret;(gdb) bt#0  __GI_raise (sig=sig@entry=6) at ../sysdeps/unix/sysv/linux/raise.c:50#1  0x00007fc37a9aa8d9 in __GI_abort () at abort.c:79#2  0x00007fc37aa054af in __libc_message (action=action@entry=do_abort, fmt=fmt@entry=0x7fc37ab14f4b "%s") at ../sysdeps/posix/libc_fatal.c:181#3  0x00007fc37aa0ca9c in malloc_printerr (str=str@entry=0x7fc37ab130e0 "free(): invalid pointer") at malloc.c:5339#4  0x00007fc37aa0e49c in _int_free (av=, p=, have_lock=0) at malloc.c:4173#5  0x000000000040120e in freeSomething(void*) ()#6  0x0000000000401401 in main ()

与后续帧相比,main() 和 freeSomething() 的内存地址相当低。由于共享对象被映射到虚拟地址空间末尾的区域,可以认为 SIGABRT 是由共享库中的调用引起的。共享对象的内存地址在多次调用之间并不是恒定不变的,所以当你看到多次调用之间的地址不同时,完全可以认为是共享对象。

堆栈跟踪显示,后续的调用源于 malloc.c,这说明内存的(取消)分配可能出了问题。

在源代码中,(即使没有任何 C++ 知识)你也可以看到,它试图释放一个指针,而这个指针并没有被内存管理函数返回。这导致了未定义的行为,并导致了 SIGABRT。

void freeSomething(void *ptr){    free(ptr);}int nTmp = 5;int *ptrNull = &nTmp;freeSomething(ptrNull);

systemd 的这个 coredump 工具可以在 /etc/systemd/coredump.conf 中配置。可以在 /etc/systemd/systemd-tmpfiles-clean.timer 中配置轮换清理转储文件。

你可以在其 手册页 中找到更多关于 coredumpctl 的信息。

用调试符号编译

打开 Makefile 并注释掉第 9 行的最后一部分。现在应该是这样的:

CFLAGS =-Wall -Werror -std=c++11 -g

-g 开关使编译器能够创建调试信息。启动应用程序,这次使用 -c2 开关。

./coredump -c2

你会得到一个浮点异常。在 GDB 中打开该转储文件:

coredumpctl debug

这一次,你会直接被指向源代码中导致错误的那一行:

Reading symbols from /home/stephan/Dokumente/core_dump_example/coredump…[New LWP 6218]Core was generated by `./coredump -c2'.Program terminated with signal SIGFPE, Arithmetic exception.#0 0x0000000000401233 in zeroDivide () at main.cpp:2929 nRes = 5 / nDivider;(gdb)

键入 list 以获得更好的源代码概览:

(gdb) list24      int zeroDivide(){25          int nDivider = 5;26          int nRes = 0;27          while(nDivider > 0){28              nDivider--;29              nRes = 5 / nDivider;30          }31          return nRes;32      }

使用命令 info locals 从应用程序失败的时间点检索局部变量的值:

(gdb) info localsnDivider = 0nRes = 5

结合源码,可以看出,你遇到的是零除错误:

nRes = 5 / 0

结论

了解如何处理转储文件将帮助你找到并修复应用程序中难以重现的随机错误。而如果不是你的应用程序,将核心转储转发给开发人员将帮助她或他找到并修复问题。


内存大对象dump linux_在 Linux 上创建并调试转储文件 | Linux 中国相关推荐

  1. Aspose.Cells使用教程:使用 .NET 在 Linux 上创建或编辑 Excel 文件

    如今自动化解决方案的出现使得电子表格自动化在各个行业中都很流行.电子表格文档是从 Web 或桌面解决方案中以编程方式创建和操作的.因此,本文介绍了如何使用 .NET 在 Linux 平台上创建 Exc ...

  2. linux上读取不到库文件,linux中make找不到库文件-lmpi的问题

    电脑上是CentoS7,已安装Intel make一个程序出现找不到库文件的错误如下: ld: skipping incompatible /opt/intel/compilers_and_libra ...

  3. Linux从头开始学--学习笔记9知识点补充-ubuntu,centos;在linux上创建c程序;linux基础命令,shell命令,vi命令,man帮助手册

    这是我从头开始学习Linux的学习笔记,后续还会更新. 记录自己的技术成长,也希望和大家分享交流,欢迎关注~ 本笔记为coursera网站课程<Linux for Developers>的 ...

  4. #内存不够,swap来凑# Linux上创建SWAP文件/分区

    转自:https://www.vmvps.com/how-to-create-a-swap-file-on-the-linux-os.html 很久很久以前,电脑的内存是个珍贵东西,于是乎就有了swa ...

  5. echo添加换行 linux_在 Linux 上创建文件的 10 个方法

    我下面将会介绍多个在 Linux 上创建文件的方法.我建议你选择几个简单高效的来辅助你的工作. -- Vinoth Kumar 我们都知道,在 Linux 上,包括设备在内的一切都是文件.Linux ...

  6. Linux上创建和更改硬链接和符号链接(软连接)

    Linux上创建和更改硬链接和符号链接(软连接) 对于Linux上的硬链接和软连接而言,使用cp命令,无论覆盖其中的那个文件(源文件,软连接文件,硬链接文件),其它文件的内容都会同步修改. 点击(此处 ...

  7. RHCSA学习 --- 在VMware上创建虚拟机并安装红帽linux系统

    RHCSA学习 - 在VMware上创建虚拟机并安装红帽linux系统 一.虚拟机创建 首先我们打开VMware,截至编辑时间最新版本已更新至16,可以自行去官网下载. 官网链接:https://ww ...

  8. linux在当前目录下创建pic目录,在Linux上创建.SO文件而不使用PIC(与位置无关的代码)(x86 32位)...

    据我所知,x86汇编代码在很大程度上受寄存器数量的限制. 当我了解到在Linux上要创建一个.so文件时,必须为gcc指定-fPIC命令行参数才能创建与位置无关的代码,我不敢首先相信它. 据我所知,e ...

  9. Linux怎么给命令创建别名,如何在Linux上创建别名和Shell函数 | MOS86

    使用别名和Bash Shell函数创建自己的Linux命令. 驯服重复性任务,截断冗长的进程,并使用您经常使用且难以记住的选项配置标准命令. 别名和Shell脚本是Linux和类似Unix的操作系统中 ...

最新文章

  1. 深度学习核心技术精讲100篇(四十七)-做推荐系统之余,我们该思考什么?
  2. 分布式ID-数据库多主模式
  3. 中国最险六大寺庙,最后一座至今无人登临
  4. vue菜鸟从业记:完成项目最后一公里之真机测试和打包上线
  5. 天津海运[600751]股票
  6. 收藏 | 一文看尽2020AI论文
  7. 【英语学习】【Level 07】U05 Best Destination L2 The City of Lights
  8. office365安装文件_Microsoft 365(原Office 365)离线下载安装教程
  9. Python模拟智能开关设备MQTT接入阿里云物联网平台 - PyCharm paho.mqtt
  10. 解决 VMWARE MAC 10.12无法全屏的问题
  11. IntelliJ IDEA 2018.2支持Java 11、MacBook Touch Bar等新特性
  12. win10绿联usb转串口_USB转串口DB9驱动安装与设置方法
  13. 软件升级 防火墙 飞塔_FortiGate软件版本升级
  14. 基于压缩传感的脉冲GPR成像技术研究(硕士学位论文初稿20120104)
  15. centos配置虚拟主机(站点)
  16. 关于网易云验证码的服务介绍
  17. 2021年施工升降机司机(建筑特殊工种)考试题及施工升降机司机(建筑特殊工种)找解析
  18. docker 网络方案--分析
  19. 手机电池电量测试软件,如何查看手机的电池电量以及如何测试电池电量
  20. python微博热点_50行Python代码,一键获取微博热点

热门文章

  1. 前端学习(1910)vue之电商管理系统电商系统之完成用户的修改
  2. 前端学习(1845)vue之电商管理系统项目实战的学习目标
  3. Java面试题19 牛客下面有关java的引用类型,说法正确的有?
  4. 第一百二十三期:免费在线制图神器!不上水印支持中文版,GitHub标星已破1万2
  5. java学习(155):序列化
  6. js udp通信_nodejs源码分析第十九章 -- udp模块
  7. feign接口调用出现连接超时
  8. 安装教程-VMware 12 安装 Windows 10 企业版
  9. hdu 4738 Caocao's Bridges 求无向图的桥【Tarjan】
  10. 回复《我要阻止做java开发的男朋友去创业型公司工作吗?》园友问题