gdb与core 最有效的调试手段之一


意外的崩溃,在日志没法有效支撑时,core dumped是一种有效的调试方法。linux的core-dump默认是关闭的,在使用时,我们需要作以下设置:

1)设置 core 的存储目录和命名格式

主要是修改配置文件 /proc/sys/kernel/core_pattern

# 1. 默认在当前程序执行目录下生成,core-程序名-程序pid-时间 [core-test-3451-1516257740]
[root@ ~]# echo "core-%e-%p-%t" > /proc/sys/kernel/core_pattern
# 2. 添加路径,可以把所有的 core 集中到一个文件夹里 [把所有的core文件放到 /root/core-file 目录下]
[root@ ~]# echo "/root/core-file/core-%e-%p-%t" > /proc/sys/kernel/core_pattern

要保证运行的程序对该目录具有写权限。

 

2)将core file的大小限制取消掉。相关命令是ulimit

// 输入目录查看状态, 0 说明是禁止生成 core 文件。
[root@ ~]# ulimit -c
0

我们可以直接在 ulimit -c 后面加上参数,当为数字时表示限制 core 文件大小不超过 1024KB[ulimit -c 1024]。但是在实际使用中一般不会设置一个固定的core大小限制。如下:

# unlimited: 字面意思,没有限制 core 文件大小。
[root@ ~]# ulimit -c unlimited
# 有些系统上,非root用户执行可能会失败,为了方便操作这里都使用root用户。

 

3)执行能产生core dump的程序。

这边提供一个例子使用 gcc -g test.c -o test进行编译。

// FILE:test.c
#include

void repeatFree(char *p)
{
    if(NULL != p)
    {
        free(p);
    }
}

int main()
{
    char* pstr =(char*) malloc(10);

    repeatFree(pstr); // 第一次释放

    repeatFree(pstr); // 第二次释放

    return 0;
}

 

[root@ ~]# ~/Workspace/logDemo/build$ ./test
free(): double free detected in tcache 2
Aborted (core dumped)

崩溃后core dumped 信息代表 相关的core文件已经产生了。

 

 

 

4)使用gdb对core文件崩溃信息进行还原:

  • gdb test core-test-1806-1646101790
  • 输入where命令可以看到导致崩溃的代码所在行数
[root@ ~]#/Workspace/logDemo/build$ gdb test core-test-1806-1646101790
GNU gdb (Ubuntu 8.1.1-0ubuntu1) 8.1.1
Copyright (C) 2018 Free Software Foundation, Inc.
License GPLv3+: GNU GPL version 3 or later //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:
//www.gnu.org/software/gdb/bugs/>.
Find the GDB manual and other documentation resources online at:
//www.gnu.org/software/gdb/documentation/>.
For help, type "help".
Type "apropos word" to search for commands related to "word"...
Reading symbols from testg...done.
[New LWP 1806]
Core was generated by `./test'.
Program terminated with signal SIGABRT, Aborted.
#0  __GI_raise (sig=sig@entry=6) at ../sysdeps/unix/sysv/linux/raise.c:51
51      ../sysdeps/unix/sysv/linux/raise.c: No such file or directory.
(gdb) where
#0  __GI_raise (sig=sig@entry=6) at ../sysdeps/unix/sysv/linux/raise.c:51
#1  0x00007f07e70a8921 in __GI_abort () at abort.c:79
#2  0x00007f07e70f1967 in __libc_message (action=action@entry=do_abort, fmt=fmt@entry=0x7f07e721eb0d "%s\n") at ../sysdeps/posix/libc_fatal.c:181
#3  0x00007f07e70f89da in malloc_printerr (str=str@entry=0x7f07e7220778 "free(): double free detected in tcache 2") at malloc.c:5342
#4  0x00007f07e710020d in _int_free (have_lock=0, p=0x557ad2529250, av=0x7f07e7453c40 ) at malloc.c:4195
#5  __GI___libc_free (mem=0x557ad2529260) at malloc.c:3134
#6  0x0000557ad1e0a6a9 in repeatFree (p=0x557ad2529260 "") at test.c:8
#7  0x0000557ad1e0a6da in main () at test.c:18
(gdb) 

 

注:在第3步在编译时使用了-g的选项, 只有在使用-g编译选项编译的程序,在gdb环境下输入where才能显示具体的行号。至于一个程序是否使用了-g选项可以使用file命令进行查看。

如下:

#使用-g选项编译的程序
[root@ ~]# file testg
testg: ELF 64-bit LSB shared object, x86-64, version 1 (SYSV), dynamically linked, interpreter /lib64/ld-linux-x86-64.so.2, for GNU/Linux 3.2.0, 
BuildID[sha1]=ffd3e3fbe1964dccfe1a43f477613cb9814667fa, with debug_info, not stripped #使用不带-g选项编译的程序 [root@ ~]# file test_ test_: ELF 64-bit LSB shared object, x86-64, version 1 (SYSV), dynamically linked, interpreter /lib64/ld-linux-x86-64.so.2, for GNU/Linux 3.2.0,
BuildID[sha1]=9057778da9314e9625bf2f4e8d05fe79907b1282, not stripped

使用-g选项编译的程序在使用file命令查看时,带有with debug_info信息。该信息在使用core调试时候具有关键的作用。使之可以显示导致崩溃的行号。