gcc/g++编译器是我们写编译C/C++程序时离不开的编译工具,而gdb又是调试C/C++程序的利器,这一篇文章我们记录一下它们的惯常用法。
gcc/g++常用编译选项
选项 | 作用 |
---|---|
-c | 生成可目标文件,但不进行链接 |
-o | 指定生成文件的文件名 |
-g | 在目标文件中添加调试信息,便于gdb调试或objdump反汇编 |
-Wall | 显示所有的警告信息(建议使用) |
-Werror | 视警告为错误,出现警告即放弃编译 |
-w | 不显示任何警告信息(不建议使用) |
-v | 显示编译步骤 |
-On | (n=0,1,2,3) 设置编译器优化等级,O0为不优化,O3为最高等级优化,O1为默认优化等级 |
-L | 指定库文件的搜索目录 |
-l | (小写的L)链接某一库 |
-I | (大写的i)指定头文件路径 |
-D | 定义宏,例如-DAAA=1,-DBBBB |
-U | 取消宏定义,例如-UAAA |
gdb常用调试命命令
我们的可执行文件要能够被gdb调试,必须在编译时加上调试信息,也即是加上-g
选项.
1 | $ gcc -g example.c -o example |
如上我们生成了一个带有调试信息的可执行文件example,要调试example可以执行下列命令:
1 | $ gdb example |
这样我们就进入了gdb的调试命令行,如下所示:
1 | GNU gdb (Ubuntu 8.1-0ubuntu3) 8.1.0.20180409-git |
如上可以看到命令行提示符为(gdb)
,接着我们就可以在这个gdb的命令行提示符上面输入各种gdb的调试命令了(补充:这里也可以在shell中输入gdb
,然后回车,这样直接进入到gdb的调试命令行,之后可以通过file example
命令来载入待调试的可执行程序)。
下面我们就以如下的程序为例,详细的看下,在gdb的调试命令行中我们都有那些命令可用:
1 |
|
查看源码
载入待调试的可执行文件之后,在gdb的命令行中输入list
或者其简写l
可以查看到程序的源码以及行号,如下:
1 | (gdb) l |
如上输入l
之后,默认会显示10行源代码,按回车之后会显示接下来的10行,直到文件的末尾。
添加断点
在gdb下添加断点使用命令break
或简写 b
,有下面几个常见用法(这里统一用 b:
1 | b 函数名 |
比如我们在 main函数和func函数上各添加一个断点:
1 | (gdb) b main |
如上我们成功加上了两个断点,在正确加上断点之后,会对应有一行输出,告诉我们断点的内存地址,断点对应的源文件名和行号。
查看断点
在加上断点之后,我们可以通过info break
命令查看断点的信息:
1 | (gdb) info break |
禁用和解禁断点
通过disable <break number>
来禁用指定Num的断点,如下我们禁用1号断点:
1 | (gdb) disable 1 |
如上,disable 1
之后,断点1的Enb
列由之前的y
变成了n
,说明断点1已被禁用。
通过eable <break number>
可以来解禁断点,如下我们对刚才禁用的断点1解禁:
1 | (gdb) enable 1 |
如上,断点1的Enb列又变成y了,它被成功解禁。
删除断点
我们可以用delete <break number>
命令来删除掉一个断点,如下我们删除断点1:
1 | (gdb) delete 1 |
如上,断点1被成功删除。
启动程序
我们可以使用run
命令或者简写r
来启动程序的执行:
1 | (gdb) r |
如上,程序执行到断点2的时候就停止执行了。
查看变量的值
p <variable name>
/print <variable name>
可以查看某一个变量的当前值:
1 | (gdb) p sum |
如上,当前sum的值为0
单步执行
next
命令或者n
可以单步执行,如下:
1 | (gdb) n |
跳入跳出函数
1 | (gdb) break 13 |
如上,我在func()函数调用行加上了断点,然后r
开始执行程序,之后程序在断点处停住,此时我执行step
命令或其简写s
来跳入func()函数内部调试,在内部依然像执行外部调试一样,如果要从函数跳出则执行finished
,这时会导致函数执行完毕,并且打印出一些函数的返回信息,并且程序停在函数后的第一条语句处。
监控变量
使用watch <varible name>
命令可以实现监控变量,使用info watch
命令可以查看监控的变量。同时break所拥有的enable
,disable
,delete
等动词对于watch依然使用,且用法大同小异。这里就不再赘述。
显示变量的值
使用display <varible name>
命令可以在每一步执行之后打印变量的当前值,如下:
1 | (gdb) start |
进入shell
shell
命令可以让我们从gdb命令行环境进入到shell的命令行环境,当我们在shell命令行环境中输入exit退出后,我们就又回到了之前的gdb命令行环境了。
可视化调试
在gdb命令行环境中输入wi
命令,可以让我们进入可视化调试环境,这个环境可以看到源代码,所使用的调试命令与上面讲到的一致。