gdb 调试基础

程序运行过程中,会产生各种各样的错误和异常信息,这些信息我们可以通过打印日志、输出文字等方式来判断和检测问题,但有的时候程序是在运行态出现故障,使用打印日志等手段没办法精准的定位问题。如果使用gdb来调试,这种问题就可以迎刃而解了。gdb 可以完全操控程序运行,让程序走就走,让程序暂停就暂停,还可以随时查看程序运行时内部变量的值等信息。

使用 gdb 调试程序必须保证符合以下两个条件。

  1. 程序可以正常编译通过
  2. 程序编译时,必须用 -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

【其他更多命令】

2015-06-29_160425

评论