【Linux】gdb安装、执行与调试
目录
debug版本与release版本的说明:
debug版本:在编译阶段会加入某些调试信息,是给程序员使用的
release版本:linux默认的版本,给用户的发行版本,没有调试信息,调试信息是在编译过程中加入到中间文件.o文件的。
使用gdb调试程序的前提是:待调试的程序中包含有调试符号信息,即生成debug版本的程序。
一、linux内安装gdb
- 参照vim安装方法
- 当再次输入为如下界面,即安装成功
二、使用gdb调试程序步骤
1.执行程序
- gdb命令run(可以简写为r)执行装载代码,在run命令之后可以指定程序运行所需要的参数。
- (gdb) r
2.调试
设置断点
- 如果程序中存在断点,则会在断点处自动暂停。通过使用gdb逐步调试代码,可以看到程序内部是如何运行的,还可以知道什么命令正在执行,变量的值的变化以及其他一些细节问题。
与断点相关命令:
- 首先,调用gdb,装载子程序:以main.c示例 $gdb main
- 如要在GDB启动后载入,使用file命令:(gdb) file main1
开始调试
gcc -o test test.c -g //编译生成test执行文件
调试信息是在编译阶段进行的,而不是链接阶段
gdb test //在gdb内调试test文件
- b +行号: 加断点
通过使用break命令(可简写为b)指定一个特定的位置设置断点。指定一个特定的位置设置断点,当程序运行到这个位置时就被中断,然后把程序的控制权交给调试器和程序员。设置断点的最简单形式——在break命令后加入行号来在该行加入断点,如下所示:
- 设置断点时也可以进行条件判断,即只有条件为真,程序到达指定行或函数时才停下来。
- (gdb) b 9 if i>9
info b / info break 查看断点信息,包括编号、类型、地址等。
- delete +断点编号 : 删除断点
图示为删除断点编号为2的断点信息
- 在delete命令后加入断点编号可以删除指定的断点。不指定断点号则删除所有的断点。
- (gdb) d 1 --删除编号为1的断点
- delete命令后面可以跟一个范围
- (gdb) d 1-6 --删除编号为1~6的断点
- 也可以使用clear来删除指定代码行上的断点。clear命令后面可以跟一个范围。
- (gdb) clear 9 --删除第9行上的所有断点
- 可以使用disable命令使某个断点暂时失效。disable命令可加断点号来禁用指定断点,否则会将所有断点禁用。断点在禁用之后可以用enable命令来恢复使用。
c 在断点后继续运行程序,可使用continue命令(简写为c)
(gdb) c
列出源代码
- 程序在载入到gdb之后,就可以通过列出源代码list命令(可简写为l)来查看源代码信息。
- (gdb) list
- list命令默认情况下只列出10行代码。如果上面命令的基础上再次输入list命令,会接着列出后面的10行代码,当然,如果后面还有10行的话,否则只列到源文件末尾。也可以通过参数来指定list命令列出源文件的某一部分。例如:列出源文件example1.c的第3~5行代码。
- (gdb) l 3,5
- list命令后也可直接跟行号,这样列出的是该行上下5行代码。
- (gdb) l 9
显示数据
- 使用print和display。display和print 是显示数据最常用的两种命令,这两个命令的功能非常强大,并不限于简单地显示一个整数值。
- 使用printf,该命令可以接受指定格式和变量列表为参数,使用起来类似于 C 中的 printf()函数。
- 内存检查命令
- gdb提供了命令examine,简写为x,来获得指针所指向的内容。
- x /format address
设置观察点(窗口)
- 观察点也称为数据断点,用来监测某个变量或表达式的值是否有变化,如果有变化,则暂停程序的运行,这在调试程序的过程中是非常有用。
- 设置观察点的命令为watch,后面跟需要查看的变量或表达式。
- (gdb) watch tol --设置变量tol的观察点
- 继续程序运行可以看到,GDB给出了变量tol的旧值0和新值1,同时也给出了下一条指令的行号和指令内容。
查看栈信息
- 当程序调用了一个函数时,函数的地址、函数参数、函数内的局部变量都会被压入“栈”(Stack)中。可以用backtrace(简写为bt)来查看当前的栈中的信息。
- 如果要查看某一层的信息,需要切换当前的栈。程序停止时,最顶层的栈就是当前栈,如果要查看栈下面层的详细信息,首先要做的是切换当前栈,可使用frame (简写为f)命令,后面跟栈帧的编号。
- (gdb) f 1
- 查看当前栈帧的详细信息,可使用info frame命令(简写为info f)。
- (gdb) info f
- 将显示调用函数的地址、被调用函数的地址、函数的编写语言、函数的参数、局部变量的地址、栈的层编号、当前的函数名、函数所在文件及行号、函数执行到的语句等信息。
程序执行控制
- 单步执行:即一步一步跟踪程序执行的流程,是经常使用的一种调试操作。GDB中可以通过step(简写为s)或next(简写为n)来单步执行代码。
- step命令可以跟踪进入函数内部,在执行到函数调用部分时,GDB会给出提示信息,包括被调用函数的入口参数、起始行号等,同时也会给出函数中将要执行的语句及所在行的行号。
- next命令也可以实现程序代码的单步执行,但它将函数调用看作是一条语句,不跟踪进入函数内部。next命令后面还可以跟参数来指定执行操作的次数,直至程序因其他原因暂停运行。
- ni 可以在汇编指令中单步执行。
- return命令:忽略当前函数剩余的语句,跳出函数并继续向下执行。return命令后可以跟变量或者表达式来作为函数的返回值。
- 执行到指定行:命令until加指定行号
- 需要注意的是如果执行中有断点则会停在断点处。
- finish命令:在退出当前函数前执行函数体
- jump命令:跳过某一段代码继续执行,从而改变程序执行的顺序。命令后跟运行转到的行号。
- 注意:jump命令不会改变程序栈的内容,所以当从一个函数跳到另一个函数后,函数返回所进行的出栈操作必定会发生错误,程序运行结果也可能非常奇怪,所以最好是在同一个函数内进行跳转
查看信息
- 查看寄存器信息:info命令,可以简写成i。
- (gdb) info registers
- 查看单个寄存器:在print命令后加上寄存器名称(前加“$”符号)。
- (gdb) p $eip
- 查看程序的汇编代码:disassemble命令
- (gdb) disassemble printinfo --显示函数printinfo的汇编代码。