欢迎光临
我们一直在努力
RackNerd Billboard Banner

GDB调试(二)

Linux服务器运维

GDB调试

运行中程序GDB调试

测试程序

//test2.c
//功能:从0开始每秒打印
#include <stdio.h>
#include <unistd.h>
int aaa();
int bbb(int n);
int main()
{
    aaa();
}

int aaa()
{
    bbb(0);
}

int bbb(int n)
{
    for(int i = n; i < n+10000; i++)
    {
        printf("i:%d\n", i);
        n++;
        sleep(1);
    }
}
gcc -g -o test2 test2.c
./test2
//结果
:0
i:1
i:2
i:3
i:4
i:5
i:6
i:7
......

操作步骤

1.运行程序

在终端窗口运行编译好的程序

./test2

2.进程ID

在另一个终端窗口,使用ps命令找到正在运行程序的进程ID,其中进程ID是第二个

ps aux | grep test2
//结果如下,其中正在运行程序的进程ID是15554
username   15554  0.0  0.0   2776  1408 pts/1    S+   22:38   0:00 ./test2
username   15557  0.0  0.0  12192  2432 pts/2    S+   22:39   0:00 grep --color=auto test

3.附加GDB

使用GDB附加到正在运行的程序上

sudo gdb test2 -p 15554

这里的sudo加不加看环境,有些不用加

4.GDB调试

在GDB中,你可以使用常用的调试命令如bt(查看调用堆栈),print(打印变量值),continue(继续执行程序),等等

这里因为sleep延时,直接continue后,test2继续运行,gdb这里卡住了,可以用CTRL-C重新中断

5.结束调试

命令 解析
detach 直接使用detach命令,可以从进程中分离GDB并让程序继续运行
attach PID 重新将GDB附加到某个进程上

GDB调试多进程

测试程序

#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>

int main()
{
        printf("begin\n");

        if ( fork() != 0 )
        {
                printf("我是父进程:进程pid=%d,父进程ppid=%d\n",getpid(),getppid());

                int ii;
                for(ii=0; ii<200; ii++)
                {
                        printf("父进程ii=%d\n",ii);
                        sleep(1);
                }
                exit(0);
                }

        else
        {
                printf("我是子进程:进程pid=%d,父进程ppid=%d\n",getpid(),getppid());
                int jj;
                for(jj=0; jj<200; jj++)
                {
                        printf("子进程jj=%d\n",jj);
                        sleep(1);
                }
                exit(0);
        }
}
gcc -g -o test3 test3.c
./test3
//运行结果
我是父进程:进程pid=5003,父进程ppid=4675
父进程ii=0
我是子进程:进程pid=5004,父进程ppid=5003
子进程jj=0
父进程ii=1
子进程jj=1
子进程jj=2
父进程ii=2
子进程jj=3
父进程ii=3
子进程jj=4
父进程ii=4
父进程ii=5
子进程jj=5
子进程jj=6
父进程ii=6
子进程jj=7
父进程ii=7
父进程ii=8
子进程jj=8
......

//开始调试
gdb test3

调试命令

命令 解析
set follow-fork-mode child 设置追踪子进程。gdb 默认调试的是父进程,如果想调试子进程,那么在用gdb调试的时候要增加。该命令要在子进程运行前设置
set detach-on-fork on/off 继续其他进程/停止其他进程。当我们调试某个进程的时候,设置别的进程是否运行。默认是on,表示调试当前进程的时候,其他的进程继续运行。off,表示调试当前进程,其他的进程被 gdb 挂起。
info inferior 通过查看可以调试的进程,方便后面切换进程
inferior processNum 可以通过 info inferior 来查看可以调试的进程,当需要切换调试的进程时,根据processNum进行切换。这里的processNum是gdb自己排的进程编号,不是进程ID

以下程序未设置命令,因此默认调试父进程,并且调试的时候子进程是运行的

eading symbols from test3...
(gdb) b 7
Breakpoint 1 at 0x1216: file test3.c, line 7.
(gdb) run
Starting program: /home/lisentao/Desktop/fatenone/project/gcc/gdb2/test3 
[Thread debugging using libthread_db enabled]
Using host libthread_db library "/lib/x86_64-linux-gnu/libthread_db.so.1".

Breakpoint 1, main () at test3.c:7
7            printf("begin\n");
(gdb) n
begin
9            if ( fork() != 0 )
(gdb) n
[Detaching after fork from child process 5242]
我是子进程:进程pid=5242,父进程ppid=5239
子进程jj=0
11                    printf("我是父进程:进程pid=%d,父进程ppid=%d\n",getpid(),getppid());
(gdb) 子进程jj=1
子进程jj=2
子进程jj=3
子进程jj=4
子进程jj=5
子进程jj=6

使用set follow-fork-mode child命令调试子进程,并使用set detach-on-fork off命令挂起父进程,随后再切换调试父进程

Reading symbols from test3...
(gdb) b 7
Breakpoint 1 at 0x1216: file test3.c, line 7.
(gdb) set follow-fork-mode child
(gdb) set detach-on-fork off
(gdb) r
Starting program: /home/lisentao/Desktop/fatenone/project/gcc/gdb2/test3
[Thread debugging using libthread_db enabled]
Using host libthread_db library "/lib/x86_64-linux-gnu/libthread_db.so.1".

Breakpoint 1, main () at test3.c:7
7 printf("begin\n");
(gdb) n
begin
9 if ( fork() != 0 )
(gdb) n
[Attaching after Thread 0x7ffff7fa9740 (LWP 5333) fork to child process 5336]
[New inferior 2 (process 5336)]
Reading symbols from /usr/lib/debug/.build-id/49/0fef8403240c91833978d494d39e537409b92e.debug...
Reading symbols from /usr/lib/debug/.build-id/41/86944c50f8a32b47d74931e3f512b811813b64.debug...
[Thread debugging using libthread_db enabled]
Using host libthread_db library "/lib/x86_64-linux-gnu/libthread_db.so.1".
[Switching to Thread 0x7ffff7fa9740 (LWP 5336)]
main () at test3.c:9
9 if ( fork() != 0 )
(gdb) n
24 printf("我是子进程:进程pid=%d,父进程ppid=%d\n",getpid(),getppid());
(gdb) n
我是子进程:进程pid=5336,父进程ppid=5333
26 for(jj=0; jj<200; jj++)
(gdb) n
28 printf("子进程jj=%d\n",jj);
(gdb) n
子进程jj=0
29 sleep(1);
(gdb) n
26 for(jj=0; jj<200; jj++)
(gdb) info inferior
Num Description Connection Executable
1 process 5333 1 (native) /home/lisentao/Desktop/fatenone/project/gcc/gdb2/test3
* 2 process 5336 1 (native) /home/lisentao/Desktop/fatenone/project/gcc/gdb2/test3
(gdb) inferior 1
[Switching to inferior 1 [process 5333] (/home/lisentao/Desktop/fatenone/project/gcc/gdb2/test3)]
[Switching to thread 1.1 (Thread 0x7ffff7fa9740 (LWP 5333))]
#0 arch_fork (ctid=0x7ffff7fa9a10) at ../sysdeps/unix/sysv/linux/arch-fork.h:52
52 ../sysdeps/unix/sysv/linux/arch-fork.h: 没有那个文件或

赞(0) 打赏
未经允许不得转载:全球主机测评 » GDB调试(二)
RackNerd Leaderboard Banner 新春特惠 服务器运维包年大优惠查看活动

觉得文章有用就打赏一下文章作者

非常感谢你的打赏,我们将继续提供更多优质内容,让我们一起创建更加美好的网络世界!

支付宝扫一扫

微信扫一扫