Linux提供了systemd-coredump服务,可以配合gdb来定位到程序崩溃位置,下面介绍它们的用法。
1. systemd-coredump
systemd-coredump的简单介绍:
systemd-coredump能从操作系统内核中获取内存转储,并能对获取到的数据进行各种处理,内存转储既可以保存到日志中,也可以保存到单独的文件中, 以便于将来被例如 gdb这样的工具做进一步的分析和处理。
默认情况下,systemd-coredump 会把内存转储事件以及可能存在的回溯(backtrace)保存到日志中, 同时把内存转储自身的数据(内存镜像)保存到外部的 /var/lib/systemd/coredump/ 目录中。
systemd-coredump 自身的行为由 /etc/systemd/coredump.conf 配置文件与对应的 /etc/systemd/coredump.conf.d/*.conf 配置片段共同决定。
参考:http://www.jinbuguo.com/systemd/systemd-coredump.html
内存转储的百度百科介绍:
内存转储是用于系统崩溃时,将内存中的数据转储保存在转储文件中,供给有关人员进行排错分析用途。而它所保存生成的文件就叫做内存转储文件。
总结
Linux的systemd-coredump服务在程序崩溃时,会将内存中的数据保存到文件中,这些文件用调试工具来定位到程序崩溃的位置,默认路径为/var/lib/systemd/coredump/。
我们可以修改/etc/systemd/coredump.conf来配置systemd-coredump服务,决定它是否启用以及转存大小。
systemd-coredump服务默认是开启的,若想关闭服务,可以在配置文件内加入以下两句话。
Storage=none
ProcessSizeMax=0
2. 用gdb定位崩溃位置
创建一个Qt例程crash_demo模拟崩溃场景,以下是我的测试用例。
放置两个按钮。
两个按钮分别绑定信号槽。
void MainWindow::on_pushButton_clicked()
{
int *a = new int;
*a = 20;
int *i = NULL;
*i = 10;
}
void MainWindow::on_pushButton_2_clicked()
{
int *i = NULL;
*i = 10;
}
在pro里添加这两句话,表示在release程序里加入调试信息。
QMAKE_CXXFLAGS_RELEASE = $$QMAKE_CFLAGS_RELEASE_WITH_DEBUGINFO
QMAKE_LFLAGS_RELEASE = $$QMAKE_LFLAGS_RELEASE_WITH_DEBUGINFO
编译运行,并且触发崩溃。
进入/var/lib/systemd/coredump/目录,可以看到出现了一个xz文件。
xz是一种压缩格式,将它解压后就能得到core文件。
把core文件移动到crash_demo的目录下,执行以下指令。
gdb ./crash_demo ./core.crash_demo.0.b0235973ffb24fec833b5390b630d757.536.1672772980000000000000
然后就能看到崩溃的函数及其行号,如下图所示。
崩溃位置在MainWindow::on_pushButton_clicked函数,行号为25行,与代码一致。
参考:https://cloud.tencent.com/developer/article/1177442