所谓调试,指的是对编写好的程序用各种手段进行查错和排错的过程。进行这种查错处理时,并不仅仅是运行一次程序检查结果,而是对程序的运行过程、程序中的变量进行各种分析和处理。本节将讲解使用gdb进行程序调试。
gdb是一个功能强大的调试工具,可以用来调试C程序或C++程序。在使用gdb这个工具进行程序调试时,主要进行下面 5 个方面的操作。
● 启动程序:在启动程序时,可以设置程序运行环境。
● 设置断点:断点就是在程序中设置的暂停程序运行的标记。程序会在断点处停止,用户便于查看程序的运行情况。这里的断点可以是行数、程序名称或条件表达式。
● 查看信息:在断点处停止后,可以查看程序的运行信息和显示程序变量的值。
● 分步运行:可以使程序逐条语句地执行,这时可以及时地查看程序信息。
● 改变环境:可以在程序运行时改变程序的运行环境和程序变量。
为了使用gdb进行程序调试,需要在编译程序时加入供gdb使用的调试信息。方法是:在编译程序时使用-g参数。在终端中输入下面的命令,在编译程序时加入调试信息。
这时,编译程序a.c,生成一个可执行程序a.bedug,这个可执行程序中加入了供调试所用的信息。
在调试文件以前,需要启动gdb。在终端中输入下面的命令。
这时,gdb的启动信息如下所示。这些提示显示了gdb的版本和版权信息。
在使用gdb调试一个程序之前,需要加载这个程序。加载程序的命令是file。在(gdb)提示符后面输入下面的命令加载程序a.debug。
命令的运行结果如下所示,显示已经加载了这个文件,并且使用了系统库文件。
使用gcc工具编译程序时加入-g参数,就可以在编译后的a.debug程序中加入断点。可以使用“list”命令显示程序的源代码和断点。下面的步骤用于查看加入断点以后的代码。
①在(gdb)提示符后面输入下面的命令。
②这时,gdb会显示第一个断点以前的代码。结果如下所示。
③这时,按“Enter”键,显示下一个断点以前的代码。结果如下所示。
④按“Enter”键,显示下一个断点以前的代码。结果如下所示。
程序运行到断点的位置会停止下来,等待用户处理信息或者查看中间变量。如果自动设置的断点不能满足调试要求,则可以用break命令增加程序的断点。
例如,需要在程序的第6 行增加一个断点,可以输入下面的命令。
这时gdb显示的结果如下所示。
输入下面的命令,在程序的第18、19、21 行增加断点。
使用“info breakpoint”命令可以查看程序中设置的断点。输入“info breakpoint”命令,结果如下所示,显示程序中所有的断点。
加上相应的断点编号,可以查看一个断点的信息。例如,下面的命令就是查看第2 个断点的信息。
显示的结果如下所示。
gdb中的run命令可以使这个程序以调试模式运行。下面的步骤用来分步运行程序,对程序进行调试。
①在(gdb)提示符后面输入“run”命令,显示的结果如下所示。
②结果显示了程序中的异常,并将异常记录到系统文件中。然后在程序的第2 个断点的位置第18 行停下。
③这时输入“next”命令,程序会在下一行停下。结果如下所示。
④输入“continue”命令,程序会在下一个断点的位置停下。结果如下所示。
⑤输入“continue”命令,程序运行到结束。结果如下所示,表明程序已经运行完毕,正常退出。
⑥step命令与next命令的作用相似,对程序实现单步运行。不同之处是,在遇上函数调用时,step函数可以进行到函数内部;而next函数只是一步完成函数的调用。
print命令可以在程序的运行过程中查看变量的值。本节将用下面的步骤来讲解变量的查看方法。
①输入下面的命令,运行程序。
②程序在第1 个断点位置停下。显示的结果如下所示。
③程序进入第18 行之前停下,并没有对i进行赋值。可以用下面的命令来查看i的值。
④显示的结果如下所示,表示i现在只是一个任意值。
⑤输入下面的命令,使程序运行一步。
⑥显示的结果如下所示。
⑦这时程序在第19 行以前停下,这时输入下面的命令,查看i的值。
⑧这时显示的i的结果如下所示,表明i已经赋值为 3。
⑨输入“step”命令,再次输入“step”命令,显示的结果如下所示。
⑩输入“step”命令,会进入到子函数中,结果如下所示。这时,显示了传递给函数的变量和值。
输入“step”命令,显示的结果如下所示,表明函数会返回变量j。
输入下面的命令,查看j的值。
显示的结果如下所示,表明j的值为 5。
这时再运行两次“step”命令,显示的结果如下所示。
输入下面的命令,查看k的值。
显示的结果如下所示,表明k的值为 5。
完成了程序的调试运行以后,输入“q”命令,退出gdb。