程序运行过程中,会产生各种各样的错误和异常信息,这些信息我们可以通过打印日志、输出文字等方式来判断和检测问题,但有的时候程序是在运行态出现故障,使用打印日志等手段没办法精准的定位问题。如果使用gdb来调试,这种问题就可以迎刃而解了。gdb 可以完全操控程序运行,让程序走就走,让程序暂停就暂停,还可以随时查看程序运行时内部变量的值等信息。
使用 gdb 调试程序必须保证符合以下两个条件。
- 程序可以正常编译通过
- 程序编译时,必须用 -g 选项
// 加入 -g 选项时程序可以被调试 gcc main.c -o main -g
【开始调试】
要调试一个程序,你只需要输入命令 “gdb 被调试程序名” 就可以了,如 gdb main
【调试中列出源码】
当进入 gdb 调试状态后,程序会等待你输入调试的命令,此时,你可以输入 list 命令(也可以使用简写 l),列出程序的源码,来决定对哪一个逻辑进行调试。每执行一次 list 都只打印 10 行代码,可以多输入几次输出完整的信息。也可以使用 “list 函数名” 来直接跳转到某个函数上。如下:
(gdb) list 1 #include <stdio.h> 2 #include <unistd.h> 3 4 int main(int argc, char* argv[]) 5 { 6 pid_t pid = fork(); 7 8 if (pid == 0) 9 { 10 // 新创建的子进程 (gdb) list 11 while (1) 12 { 13 printf("child : PID = %d, ParentID = %d\n", getpid(), getppid()); 14 sleep(1); 15 } 16 } 17 else if (pid > 0) 18 { 19 // 当前进程 20 while (1) (gdb) list 21 { 22 printf("parent: PID = %d, ParentID = %d\n", getpid(), getppid()); 23 sleep(1); 24 } 25 } 26 27 return 0; 28 }
【设置断点】
如果你想让程序在运行时,在第 11 行停止等待,你可以在 11 行使用 break 命令设置断点(也可以使用简拼 b 11),如下:
(gdb) break 11 Breakpoint 1 at 0x80484fb: file fork.c, line 11.
【查看断点信息】
如果你设置了多个断点,你可以使用 info break 命令查看断点,如下:
(gdb) info break Num Type Disp Enb Address What 1 breakpoint keep y 0x080484fb in main at fork.c:11
它显示我在 fork.c 的第 11 行设置了一个断点,编号是1、类型是断点、当前是启用状态,它的地址是什么。
【设置条件断点】
除了上面简单的断点外,也可以设定条件断点,比如我希望在第8行设定一个断点,并且当 pid == 0 的时候该断点才生效。那么可以使用 break 8 if pid = 0,添加完成后再次使用 info break 查看断点信息如下:
(gdb) info break Num Type Disp Enb Address What 1 breakpoint keep y 0x080484fb in main at fork.c:11 2 breakpoint keep y 0x080484f5 in main at fork.c:8 stop only if pid = 0
【启用/禁用某断点】
使用 info break 命令我们可以看到每一个断点的 Num 号,我们可以对这些断点进行启用和禁用,使用命令 “disable 断点编号”即可禁用某个断点,如下“
(gdb) disable 1 (gdb) info break Num Type Disp Enb Address What 1 breakpoint keep n 0x080484fb in main at fork.c:11 2 breakpoint keep y 0x080484f5 in main at fork.c:8 stop only if pid = 0
禁用后,Num 为 1 的断点 Enb 就变成了 n,相反如果想再次启用就使用 enable
【删除断点】
删除断点使用 delete 就可以。比如 delete 2,那么第2个断点就被删除了。
(gdb) delete 2 (gdb) info break Num Type Disp Enb Address What 1 breakpoint keep n 0x080484fb in main at fork.c:11
【运行被调试程序】
当你已经设定好断点等信息后,可以通过命令 run 来运行程序,程序会自动在你设定的断点位置停止。
(gdb) run Starting program: /home/mycode/0629/fork Breakpoint 1, main (argc=1, argv=0xbffff174) at fork.c:6 6 pid_t pid = fork();
【单步执行】
当卡在某断点位置时,你希望程序一步一步的向下指向,就输入 next 命令,相当于 VS 的 F10。
【单步跳入】
当程序执行到某个函数时,你希望跟踪这个函数内部的执行步骤,你可以使用 step 命令,,相当于 VS 的 F11。
【跳出】
当你希望跳出函数时,可以使用 finish 命令,相当于 VS 的 SHIFT+F11
【其他更多命令】