C++项目经验(8)—— GDB快速定位程序崩溃(coredump)在哪行

目录

背景

步骤

1.安装gdb

2.对core_file限制进行设置

3.修改core_file生成位置

4.修改CMakeLists.txt

5.将二进制文件和core一块放进gdb

6.其他注意事项


背景

写项目中,由于保护做得不够,可能发生coredump,即段错误的情况,这时手动定位会比较麻烦,因为一个项目,可能函数不断嵌套,无论是打断点,还是cout指定位置输出,都会消耗不少时间,那么,能不能,找到什么办法,直接知道程序崩在哪一行呢?(不是崩在main里哪一行,而是函数不可往下分的那一行)

步骤

1.安装gdb

sudo apt install gdb

2.对core_file限制进行设置

查看core_file限制

$ ulimit -c
$ 0

如上所示,如果你得到的结果是0,就修改一下

ulimit -c unlimited

此时,当程序崩溃时,就能生成core_file文件了

3.修改core_file生成位置

core file生成的地方是在/proc/sys/kernel/core_pattern文件定义的

改动方式如下:
 

echo "yourPath/core-%e-%p" > /proc/sys/kernel/core_pattern
# 举例
echo "/home/user/code/coredump/core-%e-%p" > /proc/sys/kernel/core_pattern

然而,有时,你的权限会不够

zsh: permission denied: /proc/sys/kernel/core_pattern

可以采用如下方式提高重定向符权限

sudo sh -c "echo "yourPath/core-%e-%p" > /proc/sys/kernel/core_pattern"

还需要说明的一点是,core-%e-%p只是一个自定义的命名方式,%字符的含义如下

%%: 相当于%
%p: 相当于<pid>
%u: 相当于<uid>
%g: 相当于<gid>
%s: 相当于导致dump的信号的数字
%t: 相当于dump的时间
%h: 相当于hostname
%e: 相当于执行文件的名称

可以按照自己的习惯去命名

4.修改CMakeLists.txt

在CMakeLists.txt里添加编译选项

add_definitions("-g")

cmake 3.12版本之后,还可以用add_compile_definitions来写,这个暂时没研究

如果你没用cmake,而是直接g++,那么g++ -g就可以了

5.将二进制文件和core一块放进gdb

现我有二进制文件MAIN,对应的core_file core-MAIN-5988 ,于是

gdb MAIN ../core_dump/core-MAIN-5988 

然后,就报具体的错误行了(不在main.cc哦)

$ gdb MAIN ../core_dump/core-MAIN-5988 

GNU gdb (Ubuntu 12.0.90-0ubuntu1) 12.0.90
Copyright (C) 2022 Free Software Foundation, Inc.
License GPLv3+: GNU GPL version 3 or later <http://gnu.org/licenses/gpl.html>
This is free software: you are free to change and redistribute it.
There is NO WARRANTY, to the extent permitted by law.
Type "show copying" and "show warranty" for details.
This GDB was configured as "x86_64-linux-gnu".
Type "show configuration" for configuration details.
For bug reporting instructions, please see:
<https://www.gnu.org/software/gdb/bugs/>.
Find the GDB manual and other documentation resources online at:
    <http://www.gnu.org/software/gdb/documentation/>.

For help, type "help".
Type "apropos word" to search for commands related to "word"...
Reading symbols from MAIN...
[New LWP 5988]
[Thread debugging using libthread_db enabled]
Using host libthread_db library "/lib/x86_64-linux-gnu/libthread_db.so.1".
Core was generated by `./MAIN'.
Program terminated with signal SIGSEGV, Segmentation fault.
#0  0x0000558b2b50b1f5 in Test<int, double>::fun_err (this=<synthetic pointer>)
    at /home/ain/Documents/code/include/test.h:24
--Type <RET> for more, q to quit, c to continue without paging

倒数第二行就告诉了你,错误在test.h的第24行,这时你按照最后一行的提示输入c,这一行的内容就会显示出来

Core was generated by `./MAIN'.
Program terminated with signal SIGSEGV, Segmentation fault.
#0  0x0000558b2b50b1f5 in Test<int, double>::fun_err (this=<synthetic pointer>)
    at /home/ain/Documents/code/include/test.h:24
--Type <RET> for more, q to quit, c to continue without paging--c
24	    std::cout << p->first << std::endl;

至此,我们就定位到了具体出错在哪一行了

6.其他注意事项

ulimit -c和echo指令写入自定义路径,前者只在当前shell有效,后者由于写入了系统文件,因此持续有效

因此如果退出当前shell,core_file大小会重新变成0。其实这样也好,不随便产生coredump文件,给你一个手动控制开关的权力,但如果你想一直持续开启的话,可以将ulimt -c unlimited直接写入相应的shellrc中(如~/.bashrc   ~/.zshrc)

希望能帮到大家!

  • 6
    点赞
  • 22
    收藏
    觉得还不错? 一键收藏
  • 4
    评论
你好!要调试核心转储文件(core dump),你可以使用GDB(GNU调试器)。下面是一些基本的步骤: 1. 确保你的程序在编译时启用了调试信息。使用 `-g` 标志进编译,例如:`gcc -g myfile.c -o myprogram`。 2. 运程序并生成 core dump 文件。你可以通过执以下命令来启用核心转储:`ulimit -c unlimited`。然后运程序,当它崩溃时,会生成一个名为 `core` 的文件。 3. 使用 GDB 载入核心转储文件和可执文件。执以下命令:`gdb -c core myprogram`,其中 `core` 是核心转储文件的路径,`myprogram` 是可执文件的路径。 4. 开始调试。一旦 GDB 加载了核心转储文件和可执文件,你就可以开始调试了。你可以使用各种 GDB 命令来检查崩溃发生的位置、回溯信息、变量的值等。 以下是一些常用的 GDB 调试命令: - `run`:重新运程序。 - `backtrace`(或 `bt`):显示回溯信息。 - `print <variable>`(或 `p <variable>`):打印变量的值。 - `break <line>`(或 `b <line>`):在指定设置断点。 - `continue`(或 `c`):继续执程序。 - `step`(或 `s`):单步执程序。 - `next`(或 `n`):按程序,不进入函数。 - `quit`(或 `q`):退出 GDB。 这只是一些基本的调试命令,你可以根据需要查阅 GDB 的文档来了解更多详细信息。希望对你有帮助!如果还有其他问题,请随时提问。

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 4
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值