【Linux】gdb安装、执行与调试

目录

一、linux内安装gdb

二、使用gdb调试程序步骤

1.执行程序

2.调试

设置断点

开始调试


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的汇编代码。