本章讲解知识点

    1. GDB 调试 core 文件
    1. GDB 调试多线程

  • 本专栏适合于软件开发刚入职的学生或人士,有一定的编程基础,帮助大家快速掌握工作中必会的工具和指令
  • 本专栏针对面试题答案进行了优化,尽量做到好记、言简意赅
  • 如专栏内容有错漏,欢迎在评论区指出或私聊我更改,一起学习,共同进步。
  • 相信大家都有着高尚的灵魂,请尊重我的知识产权,未经允许严禁各类机构和个人转载、传阅本专栏的内容。

好了,自从我们可以使用华为云服务器后,我们鸟枪换大炮,开启了新的学习之旅,接下来我们就学习 GDB 进阶内容。


1. GDB 调试 core 文件

调试 core 文件是必须掌握的能力。

1.1. 为什么调试 core 文件

通常情况下,core 文件会包含了程序运行时的内存,寄存器状态,堆栈指针,内存管理信息还有各种函数调用堆栈信息等,我们可以理解为是程序工作当前状态存储生成第一个文件,许多的程序出错的时候都会产生一个 core 文件,通过工具分析这个文件,我们可以定位到程序异常退出的时候对应的堆栈调用等信息,找出问题所在并进行及时解决。

1.2. 如何调试 core 文件

我们上一节已经成功创建了源文件并编译运行成功:

root@hecs-x-large-2-linux-20210727143552:/home# cat douya.c
#include <stdio.h>

int main(){
        int i = 0;
        int temp = 1;

        for (i; i <= 10; i++){
                temp *= i;
                printf("hello douya!\n");
        }

        int *p = NULL;
        *p = 10;

        return 0;
}

root@hecs-x-large-2-linux-20210727143552:/home# gcc -g douya.c -o douya
root@hecs-x-large-2-linux-20210727143552:/home# ./douya
hello douya!
hello douya!
hello douya!
hello douya!
hello douya!
hello douya!
hello douya!
hello douya!
hello douya!
hello douya!
hello douya!
Segmentation fault (core dumped)

其实很明显,我们代码的第 13、14 行,一个空指针修改其内容,会出现内存错误。我们运行的时候提示 Segmentation fault (core dumped) ,说明报错,而且这个时候 (core dumped) 说明已经产生了 core 文件。

有些同学没有这个显示,说明是这个文件的 core 属性没有开启。我们输入查看命令 ulimit -a

root@hecs-x-large-2-linux-20210727143552:/home# ulimit -a
core file size          (blocks, -c) 0
data seg size           (kbytes, -d) unlimited
scheduling priority             (-e) 0
file size               (blocks, -f) unlimited
pending signals                 (-i) 15527
max locked memory       (kbytes, -l) 65536
max memory size         (kbytes, -m) unlimited

其中 core file size (blocks, -c) 0 就是属性,显示产生的文件大小为 0,这样不行的,我们得开启权限。

输入:

root@hecs-x-large-2-linux-20210727143552:/home# ulimit -c unlimited
root@hecs-x-large-2-linux-20210727143552:/home# ulimit -a
core file size          (blocks, -c) unlimited
data seg size           (kbytes, -d) unlimited
scheduling priority             (-e) 0
file size               (blocks, -f) unlimited
pending signals                 (-i) 15527
max locked memory       (kbytes, -l) 65536
max memory size         (kbytes, -m) unlimited

可以注意到,产生 core 文件的大小不再受到限制了。我们再次编译运行:

root@hecs-x-large-2-linux-20210727143552:/home# gcc -g douya.c -o douya
root@hecs-x-large-2-linux-20210727143552:/home# ./douya
hello douya!
hello douya!
hello douya!
hello douya!
hello douya!
hello douya!
hello douya!
hello douya!
hello douya!
hello douya!
hello douya!
Segmentation fault (core dumped)
root@hecs-x-large-2-linux-20210727143552:/home# ls -a  // 查看目录下文件
.  ..  core  douya  douya.c

我们可以很清楚地看到,目录下生成了一个 core 文件

我们来调试 core 文件,输入命令:

root@hecs-x-large-2-linux-20210727143552:/home# gdb douya core
GNU gdb (Ubuntu 8.1.1-0ubuntu1) 8.1.1
Copyright (C) 2018 Free Software Foundation, Inc.

Core was generated by `./douya'.
Program terminated with signal SIGSEGV, Segmentation fault.
#0  0x0000557a0457567e in main () at douya.c:13
13              *p = 10;

可以看到,瞬间就定位到了有问题的地方。

1.3. 一个正在运行的程序如何生成 core 文件

有时候我们的程序在后台运行,我们不知道它什么时候会崩溃才产生 core 文件,所以要采用另一种方法。

好了,我们来修改源文件,让它运行在后台:

root@hecs-x-large-2-linux-20210727143552:/home# vim douya.c  // 编辑
root@hecs-x-large-2-linux-20210727143552:/home# cat douya.c  // 查看内容
#include <stdio.h>

int main(){
        int i = 0;
        int temp = 1;

        while (1){

                for (i; i <= 10; i++){
                        temp *= i;
                }

        }

        int *p = NULL;
        *p = 10;

        return 0;
}
root@hecs-x-large-2-linux-20210727143552:/home# gcc -g douya.c -o douya  // 编译
root@hecs-x-large-2-linux-20210727143552:/home# ls   // 查看目录下文件
douya  douya.c
root@hecs-x-large-2-linux-20210727143552:/home# ulimit -c   // 查看core属性
unlimited

root@hecs-x-large-2-linux-20210727143552:/home# ./douya &   // 后台运行
[2] 19386  // douya 这个进程的PID
root@hecs-x-large-2-linux-20210727143552:/home# ps aux | grep douya  // 查看进程
root     19374 99.8  0.0   4516   764 pts/3    R    16:15   2:31 ./douya
root     19386 99.5  0.0   4384   796 pts/3    R    16:17   0:16 ./douya

root@hecs-x-large-2-linux-20210727143552:/home# gdb attach 19386  // attach PID
GNU gdb (Ubuntu 8.1.1-0ubuntu1) 8.1.1

(gdb) gcore test.core    // 生成 core 文件
Saved corefile test.core

root@hecs-x-large-2-linux-20210727143552:/home# kill -9 19386  // 终止douya进程
root@hecs-x-large-2-linux-20210727143552:/home# ps aux | grep douya
root     19374 99.9  0.0   4516   764 pts/3    R    16:15   6:27 ./douya
root     19404  0.0  0.0  14436  1152 pts/3