gdb笔记
启动gdb
可以通过gdb -q
命令启动gdb(-q会忽略启动时的提示信息)。
可以在gdb中查看当前的工作目录:
(gdb) pwd
gdb中也可以自由切换工作目录:
(gdb) cd workspace/cpp-study/hello-cpp/
加载要调试的可执行文件:
(gdb) file bin/hello-cpp
启动调试程序,run
和start
命令都可以启动程序,区别就是run
直接运行程序,start
在进入main
之后暂停运行,相当于在main
的开头设置了断点:
(gdb) start
普通断点
设置断点的命令是break
,可以简写为b
,断点语法如下:
- b linenum:linenum 是一个整数,表示要打断点处代码的行号。
- b filename:linenum:filename 表示源程序文件名;linenum 为整数,表示具体行数。
- b +offset:假设offset为2,+offset 表示以当前程序暂停位置(例如第 4 行)为准,向后数 offset 行处(第 6 行)打断点。
- b -offset:假设offset为2,-offset 表示以当前程序暂停位置(例如第 4 行)为准,向后数 offset 行处(第 2 行)打断点。
- b function:function 表示程序中包含的函数的函数名,即 break 命令会在该函数内部的开头位置打断点,程序会执行到该函数第一行代码处暂停。
- b filename:function:filename 表示远程文件名;function 表示程序中函数的函数名。整体的意思是在指定文件 filename 中 function 函数的开头位置打断点。
设置临时断点的命令是tbreak
,该断点执行一次就自动消失,用法和break
一样。
还有可以进行函数名正则表达式匹配的rbreak
命令,tbreak 命令的使用语法格式为:
(gdb) tbreak regex
其中 regex 为一个正则表达式,程序中函数的函数名只要满足 regex 条件,tbreak 命令就会其内部的开头位置打断点。值得一提的是,tbreak 命令打的断点和 break 命令打断点的效果是一样的,会一直存在,不会自动消失。
单步调试
- next:next 是最常用来进行单步调试的命令,其最大的特点是当遇到包含调用函数的语句时,无论函数内部包含多少行代码,next 指令都会一步执行完。也就是说,对于调用的函数来说,next 命令只会将其视作一行代码。
next 命令可以缩写为 n 命令,使用方法也很简单,语法格式如下:
(gdb) next count
参数 count 表示单步执行多少行代码,默认为 1 行。
- step:通常情况下,step 命令和 next 命令的功能相同,都是单步执行程序。不同之处在于,当 step 命令所执行的代码行中包含函数时,会进入该函数内部,并在函数第一行代码处停止执行。
step 命令可以缩写为 s 命令,用法和 next 命令相同。
- until:不带参数的 until 命令,可以使 GDB 调试器快速运行完当前的循环体,并运行至循环体外停止。
- finish:结束当前正在执行的函数,并在跳出函数后暂停程序的执行。
- return:结束当前调用函数并返回指定值,也就是说,如果当前函数还有剩余的代码未执行完毕,也不会执行了,到上一层函数调用处停止程序执行。
删除断点
借助如下指令,可以查看当前调试环境中存在的所有断点,包括普通断点、观察断点以及捕捉断点:
(gdb) info breakpoint [n]
(gdb) info break [n]
参数 n 作为可选参数,为某个断点的编号,表示查看指定断点而非全部断点。
无论是普通断点、观察断点还是捕捉断点,都可以使用 clear 或者 delete 命令进行删除。
clear 命令可以删除指定位置处的所有断点,常用的语法格式如下所示:
(gdb) clear location
参数 location 通常为某一行代码的行号或者某个具体的函数名。当 location 参数为某个函数的函数名时,表示删除位于该函数入口处的所有断点。
delete 命令(可以缩写为 d )通常用来删除所有断点,也可以删除指定编号的各类型断点,语法格式如下:
delete [breakpoints] [num]
其中,breakpoints 参数可有可无,num 参数为指定断点的编号,其可以是 delete 删除某一个断点,而非全部。