文章目录
- 前言
- 一、数据断点
- 二、x查看内存命令
- 三、深入info命令
- 四、调试中的技巧
- 总结
前言
本篇文章我们继续讲解GDB调试。
一、数据断点
在 GDB (GNU Debugger) 中,数据断点是一种断点类型,它允许你在程序访问指定内存地址的数据时暂停程序的执行。通过设置数据断点,你可以监视和调试特定内存位置的读取或写入操作。
以下是在 GDB 中设置数据断点的基本用法:
1.启动 GDB 并加载可执行文件:
gdb executable_file
2.选择要设置数据断点的内存地址。你可以使用以下方式之一:
使用变量名或指针来指定内存地址
使用表达式计算所需内存地址
3.使用 watch 命令设置数据断点:
(gdb) watch *address
其中 address 是你选择的内存地址。通过在地址前加上 * 来指示监视该地址的数据访问。
例如,如果你要监视一个 int 类型的变量 x,你可以这样设置数据断点:
(gdb) watch *(&x)
当程序访问被设置为数据断点的内存地址时,程序的执行将暂停,并返回到 GDB 提示符下。
5.在数据断点暂停时,你可以执行各种调试操作,如打印变量值、单步执行、查看回溯信息等。
二、x查看内存命令
在 GDB(GNU Debugger)中,x 命令用于以指定格式打印内存区域的内容。它允许你查看内存中存储的数据,并以不同的格式(例如十六进制、十进制、ASCII 码等)对数据进行呈现。
x 命令的基本语法如下:
x/[显示数量][打印格式] 内存地址
显示数量 是要显示的单位数量,默认为1。
打印格式 是指定要使用的输出格式,例如 x(十六进制)、d(十进制)、o(八进制)、u(无符号十进制)、t(二进制)等。GDB 还支持其他格式选项,可以参考 GDB 的文档了解更多细节。
内存地址 是你要查看的内存区域的地址表达式。
下面是一些示例,演示了不同的使用方式:
(gdb) x address
2.查看一定数量的内存地址的值:
(gdb) x/5 address
首先定义一个大小为5的一维数组:
#include <stdio.h>
#include <unistd.h>
int main(int argc, char** argv)
{
int i = 0;
int a[5] = {1, 2, 3, 4, 5};
for(i = 0; i < 5; i++)
{
printf("%d\n", i);
sleep(1);
}
printf("success complte\n");
return 0;
}
查看一维数组中的数据值:
3.使用不同的打印格式:
(gdb) x/d address # 十进制格式
(gdb) x/o address # 八进制格式
(gdb) x/t address # 二进制格式
(gdb) x/s address # 字符串格式
4.查看结构体或数组的内存内容:
(gdb) x/4w &struct_var # 以四个字为单位查看结构体的内容
(gdb) x/16xb &array # 以字节为单位查看数组的内容
三、深入info命令
在讲解info命令之前我们先来讲解一下step命令:
GDB中的"step"命令用于逐行执行代码并进入函数内部。它允许你以单步模式执行程序,逐行跟踪代码执行过程,包括进入调用的子函数内部。
“step n”:执行完当前行后进入下一个函数调用的内部n次,然后暂停执行,n为整数。
“stepi”:逐指令执行程序,而不是逐行执行。
“finish”:执行到当前函数的结尾,并停在调用该函数的下一行。
这里编写了一个Test函数:
#include <stdio.h>
#include <unistd.h>
int Test(int a, int b)
{
int c = a + b;
return c;
}
int main(int argc, char** argv)
{
int i = 0;
Test(2, 3);
printf("success complte\n");
return 0;
}
首先将断点打在Test函数这里,使用step命令进入函数内部:
下面是有关一些info命令的讲解:
1.info registers:该命令用于显示当前CPU寄存器的状态和值。它可以显示通用目的寄存器(如EAX、EBX、ECX等)以及特殊寄存器(如程序计数器PC、堆栈指针SP等)。这对于理解程序执行状态和调试寄存器相关问题非常有用。
2.info args:该命令用于显示当前函数的参数及其值。它会列出函数的参数名称和值,可帮助你了解函数调用时传递的实际参数值。
3.info locals:该命令用于显示当前函数的局部变量及其值。它会列出函数内部声明的局部变量的名称和值,可帮助你了解函数内部变量的状态。
4.info frame:该命令用于显示当前帧(函数调用栈帧)的信息。它会显示函数名称、参数、返回地址等与当前帧相关的信息。
5.info variables:该命令用于显示当前作用域内的所有变量和它们的值。它会列出当前作用域中定义的变量的名称和值。可以使用该命令查看全局变量或其他作用域的变量状态。
6.info functions:该命令用于显示已加载程序的所有函数列表。它会列出可执行文件中定义的所有函数的名称,提供了一个快速查看程序中可用函数的方式。
四、调试中的技巧
1.display /f expression:
该命令用于设置一个表达式的自动显示。每次程序暂停时,GDB 将自动显示该表达式的值。 /f 可以是省略号(…)、空格或/format,用于指定显示格式。例如,display /x $eax 将以十六进制格式显示寄存器 $eax 的值。
2.undisplay:
该命令用于取消之前设置的自动显示。你可以提供要取消显示的显示编号,也可以不带参数使用该命令来取消所有的显示。
3.whatis:
该命令用于获取给定标识符的类型信息。例如,whatis variable_name 将显示变量 variable_name 的类型。
4.ptype:
该命令用于显示给定类型的详细信息。例如,ptype struct_name 将显示结构体 struct_name 的详细成员变量和类型信息。
5.list:
该命令用于显示源代码中的代码片段。你可以指定一个函数名、行号或文件名作为参数。例如,list function_name 将显示函数 function_name 的代码。
6.set listsize N:
该命令用于设置 list 命令显示的代码行数。默认情况下,它显示 10 行代码,但可以通过设置 N 来更改显示的行数。
7.shell:该命令用于在 GDB 提示符下运行操作系统的命令。例如,shell ls 将执行 ls 命令,并显示目录中的文件列表。
总结
本篇文章就讲解到这里,掌握了GDB调试,在编写Linux程序中寻找BUG和调试将会非常高效。