Linux GDB调试
一、准备工作
编译选项设置
-g、-ggdb
GCC为此提供了两个选项:-g和-ggdb。后者添加特定于GDB的调试信息,而前者则为您正在使用的任何目标操作系统以适当的格式生成信息,使其成为更具可移植性的选项。
在我们的特殊情况下,目标操作系统始终是Linux,使用-g还是-ggdb没有什么区别。
这两个选项都允许指定调试信息的级别从0到3。
0:不产生任何调试信息,相当于省略-g或ggdb开关;
1:这产生最少的信息,但包括函数名和外部变量,这足以产生回溯;
2:这是默认值,包含有关局部变量和行号的信息,以便您可以执行源代码级调试和单步执行代码;
:这包括额外的信息,除其他事项外,意味着GDB可以正确处理宏扩展
-gdwarf-2
产生DWARF version2 的格式的调试信息
备注:编译时添加-gdwarf-2和-g3这两个参数就可以调试宏定义。
代码优化级别
编译器优化倾向于破坏源代码行和机器码行之间的关系,这使得遍历源代码变得不可预测。gdb调试需要在不进行优化的情况下进行编译,省略-O编译开关,或者使用-Og,该开关启用不会干扰调试的优化。
二、命令说明
启动命令
gdb [option] 程序名 [corefile]
-q: 不显示gdb版本信息
示例: gdb -q ./test
调试命令
run(r): 开始调试程序
where: 显示导致段错误的执行函数树
backtrace(bt): 打印函数调用堆栈
frame(f): 选择特定的堆栈帧进行检查
list[m,n]: m,n是要显示包含错误首次出现位置的起始行和结尾行,不带参数的list命令将显示附近的10行代码
print(r): 打印变量
break(b): 设置断点
break linenum(行号)
break funcname(函数名)
break filename:linenum
break filename:funcname
continue(c): 从断点以后继续执行,并非单步
delete(d): 删除一个端点
语法格式:delete 断点编号
断点编号是由"info break"获取的
info break: 查看已设置断点的信息
set variable: set variable varname=value;varname是变量名称,value是变量的新值
示例 set args -c conf/nginx.conf
step(s): 当遇到一个函数的时候,step将进入函数,每次执行一条语句,相当于vs中的F10命令
next(n): 当遇到一个函数的时候,next将执行整个函数,相当于vs中的F5命令
return: 相当于在函数中直接return ,并且将value作为返回值返回给调用者
DIR: 加载源文件目录,如果调试的文件不在当前目录下,需要将文件目录加载到程序中,如果在当前目录下不需要加载目录
until: 跳出循环
until linenum 执行到一个比当前行号大的行,或者也可以指定在当前frame中的某一行
finish: 执行,直到选定的frame执行结束,然后打印返回值,将其放入历史值中,停止
set print elements N: 指定打印的长度,对长字符串特别有用
set print element 0 输出完整的字符串
set print pretty 设置GDB打印结构的时候,每行一个成员,并且有相应的缩进,缺省是关闭的
三、拦截信号
Handle命令可控制信号的处理,他有两个参数,一个是信号名,另一个是接受到信号时该作什么。几种可能的参数是:
* nostop 接收到信号时,不要将它发送给程序,也不要停止程序。
* stop 接受到信号时停止程序的执行,从而允许程序调试;显示一条表示已接受到信号的消息(禁止使用消息除外)
* print 接受到信号时显示一条消息
* noprint 接受到信号时不要显示消息(且隐含着不停止程序运行)
* pass 将信号发送给程序,从而允许你的程序去处理它、停止运行或采取别的动作。
* nopass 停止程序运行,但不要将信号发送给程序。
# 截获SIGPIPE信号,程序停止并打印信息
handle SIGPIPE stop print
# 忽略SIGUSR1信号
handle SIGUSR1 nostop noprint
四、多线程调试
info threads: 列出程序中的所有线程
thread number: 选择特定的线程进行检查
五、多进程调试
set follow-fork-mode [parent|child] 命令用于控制GDB在程序调用fork()后应该跟踪哪个进程:父进程还是子进程。这个命令对于调试涉及fork()调用的程序特别有用。
parent:GDB在fork()之后继续调试父进程,子进程则继续独立运行。
child:GDB在fork()之后调试子进程,父进程则继续独立运行。
浙公网安备 33010602011771号