事实证明有时候无聊的东西反而变成了一篇博文,谁叫恶趣味的C语言作业非要求用word写实验报告,本猹宁可先写成Markdown再复制粘贴过去。
首先按照惯例应该介绍下GDB,搭配GCC使用的调试器,也是众多使用GCC为编译器的IDE的默认调试器(大概?),虽然无聊的实验报告模板还很搞笑的写了一个部分叫XXX调试器和VC6.0的比较(看戏的内心:我看过两年学生出生时间比VC6还晚的时候这些课还怎么拿VC6讲)。
所以掌握GDB的使用还是很有必要的,毕竟掌握某个使用GDB的IDE终究只是掌握了一个图形壳子,原理估计还是要深入一层到直接用GDB(强行接入正经模式)。
这里只是按照实验报告的要求写一下断点调试和单步执行的用法(PS:Word实在是太难用了,字号缩进和标题序号就没有按照我想要的方式工作过。
准备
调试模式编译程序
首先应该明确调试的实现方式,GDB能够暂时的停下程序操作程序其实是通过向编译过程中的二进制流中添加钩子(HOOKS)来实现的。但是对于一个正常的,打算释出给用户使用的程序而言不应该以调试模式编译,因为这些添加进去的钩子不但会增大文件体积,还会降低程序的运行效率。所以GCC默认编译程序的时候时不会添加这个钩子的,需要的时候以-g
参数来启用调试模式。
本例中以文件Lab2.c为例,使用命令
将它编译到可执行文件lab。
用GDB打开程序。
打开程序的命令很简单,就是$ gdb lab
,但是有可能遇到的问题是程序要处理命令行参数,在使用GDB的时候是不能直接在命令行后面附加程序参数的,需要使用参数可以在打开GDB之后输入set args 参数1 参数2 ...
附加上参数。
用GDB打开程序之后是一个交互界面,显示了一些信息和(gdb)
这个提示符,表示你现在是在和GDB进行交互而不是程序。这个时候程序是不会运行的。
调试
设置断点
首先使用break
指令就可以添加一个断点,断点顾名思义就是程序运行到这个位置会暂停下来交给GDB,这样你才能够在程序运行到一半的时候查看一些可疑的变量,断点是针对函数使用的,比如我想在所有的printf()进入的时候暂停,可以使用:
显示的是这样的:
当然接下来可以继续添加更多的断点。
然后使用run
就可以让程序跑起来:
这时候使用print
指令可以打印任意的内容:
使用bt
指令可以显示出程序的栈(Backtrace):
输入c
就是继续运行程序的意思。但是step
指令的功能更加有用,顾名思义这个就是单步运行,每次只运行一行代码,这是个step-in的模式,即如果该行有函数则进入函数内一行一行运行,而next
则是step-over的模式,即如果该行有函数会运行函数返回结果而不是进入函数内部。
如果不输入指令直接回车,就是重复上一条指令,程序运行结束之后可以使用quit
指令退出GDB。
好了本猹要去补作业了。