core文件与gdb调试

  1、核心转储文件(core dump file),下文简称core文件。

  1)简介:某些信号(如SIGQUIT、SIGABRT和SIGSEGV)的默认动作就是引起进程终止并产生core文件。该文件包含进程终止时的内存镜像,用于在调试时探测程序终止时的状态,以随时重现错误。

  coredump的开启和关闭:用ulimit -a查看若core file size这一项为0,说明coredump没开启。ulimit -c可以开启coredump并指定最大能产生的core文件(0表示关闭coredump)。默认不产生core文件,因为它可能包含敏感信息。

  默认的core文件名为core,且在当前目录产生。/proc/sys/kernel/core_pattern定义了core文件的存放目录和命名方式(如/data/coredump/core_%e_%t。其中,%e表示可执行文件名、%t表示coredump的时间、%p表示PID、%s表示引发coredump的信号值等)。另外,若/proc/sys/kernel/core_uses_pid的内容是非0值,则core文件名会把进程ID作为扩展(***.pid)。

  2)使用core文件进行调试。例子:

int main()
{   
    int *p = 0;
    cout << *p << endl;
}

  步骤:(1)开启coredump:ulimit -c unlimited;(2)编译:g++ test.cpp -g;(3)执行:./a.out,出现错误Segmentation fault (core dumped)并产生文件core;(4)调试:gdb ./a.out core

  3)通过管道将核心转储信息重定向给一个进程,而不是写入到磁盘文件。

  Linux从内核2.6.19开始,若/proc/sys/kernel/core_pattern的首字符是'|'(管道),则该行剩下部分将被解析为一个程序及其命令行参数,并在某个进程发生coredump时被执行。coredump的核心转储信息被重定向到该程序的标准输入。

  注意:core_pattern中的程序名必须是绝对路径,且紧跟在'|'后面;该程序以root用户/组运行;可指定命令行参数(从Linux 2.6.24开始),如%p表示发生coredump的进程ID,但行的最大长度为128字节。以下是man core中的例子:

// core_pattern_pipe_test.c
//
忽略错误处理逻辑 #define BUF_SIZE 1024 int main(int argc, char *argv[]) { // 将目录切换到发生coredump的进程的工作目录。argv[1]即core_pattern文件的%p char cwd[PATH_MAX]; snprintf(cwd, PATH_MAX, "/proc/%s/cwd", argv[1]); chdir(cwd); FILE *fp = fopen("core.info", "w+"); // 在core.info中写入发生coredump的进程的信息 int j = 0; fprintf(fp, "argc=%d ", argc); for (j = 0; j < argc; j++) { fprintf(fp, "argc[%d]=<%s> ", j, argv[j]); } // 核心转储信息的字节数 int tot = 0; ssize_t nread; char buf[BUF_SIZE]; while ((nread = read(STDIN_FILENO, buf, BUF_SIZE)) > 0) { tot += nread; } fprintf(fp, "Total bytes in core dump: %d ", tot); exit(EXIT_SUCCESS); }

  编译得到core_pattern_pipe_test(在/home/hanerfan/programming目录) -> 将/proc/sys/kernel/core_pattern的内容改为"|/home/hanerfan/programming/core_pattern_pipe_test %p UID=%u GID=%g sig=%s"

  执行sleep 100,然后按Ctrl+,则sleep进程被SIGQUIT信号终止并产生核心转储信息 -> 因为core_pattern首字符为'|',因此执行/home/hanerfan/programming/core_pattern_pipe_test %p...。core.info中写入了一些核心转储信息,如下:

~/programming$ sudo cat core.info 
argc=5
argc[0]=</home/hanerfan/programming/core_pattern_pipe_test>
argc[1]=<5314>
argc[2]=<UID=1000>
argc[3]=<GID=1000>
argc[4]=<sig=3>
Total bytes in core dump: 356352

  2、gdb调试

  1)gdbserver:Remote Server for the GNU Debugger。远程调试。

  (1)安装

yum install gdb-gdbserver.x86_64 # 可先用yum search gdbserver搜索到对应的安装包

  (2)运行

  I、服务器:执行gdbserver localhost:2345 ./a.out(在2345端口上监听远程gdb请求,a.out为被调试的程序)。

  II、客户端:

[root@localhost siosvr]# gdb
(gdb) file a.out 
(gdb) target remote 192.168.32.101:2345 # 客户端和服务器建立了连接(101为服务器地址)。
(gdb) b 10 # 设置断点
(gdb) continue # 服务器端的a.out开始运行,并在该断点处“暂停”
(gdb) continue # 服务器端的a.out正常退出,GDBserver退出

 

不断学习中。。。

原文地址:https://www.cnblogs.com/hanerfan/p/3380938.html