2. 查看变量与内存内容
任务目标
使用GDB的print和x命令,在程序运行时查看变量当前值、变量地址以及指定内存区域的内容,从而观察数据在程序执行过程中的变化。
环境与依赖
- Linux环境,安装
gcc和gdb - 编译时添加
-g选项保留调试符号
示例程序
创建文件var_demo.c,内容如下:
#include <stdio.h>
#include <string.h>
typedef struct {
int id;
char name[16];
float score;
} Student;
int main() {
int count = 3;
int arr[4] = {10, 20, 30, 40};
char msg[] = "GDB-Demo";
Student stu = {1001, "Tom", 88.5f};
printf("count=%d, arr[0]=%d, msg=%s, stu.id=%d\n",
count, arr[0], msg, stu.id);
// 修改数据,便于观察变化
count = 5;
arr[2] = 99;
strcpy(msg, "Changed");
stu.score = 95.0f;
printf("After modification: count=%d, arr[2]=%d, msg=%s, stu.score=%.1f\n",
count, arr[2], msg, stu.score);
return 0;
}
编译:
gcc -g -o var_demo var_demo.c
GDB调试步骤
启动GDB并设置断点:
gdb ./var_demo
(gdb) break var_demo.c:15
(gdb) run
程序在第一个printf处暂停,此时执行以下命令查看变量:
(gdb) print count
$1 = 3
(gdb) print arr
$2 = {10, 20, 30, 40}
(gdb) print arr[2]
$3 = 30
(gdb) print msg
$4 = "GDB-Demo"
(gdb) print stu
$5 = {id = 1001, name = "Tom", score = 88.5}
(gdb) print &count
$6 = (int *) 0x7fffffffe1ac
(gdb) print &stu
$7 = (Student *) 0x7fffffffe190
使用x命令查看内存内容(地址以上述输出为准,实际地址可能不同):
(gdb) x/4dw &arr
0x7fffffffe190: 10 20 30 40
(gdb) x/8cb msg
0x7fffffffe1b0: 71 'G' 68 'D' 66 'B' 45 '-' 68 'D' 101 'e' 109 'm' 111 'o'
(gdb) x/3uw &stu
0x7fffffffe1c0: 1001 1818581860 1120403456
说明:x/4dw表示以4个十进制有符号字(4字节为单位)显示;x/8cb表示以8个单字节字符形式显示;x/3uw表示以3个无符号字显示。结构体stu的内存中,name字段的ASCII码值("Tom")以十六进制显示为0x54 0x6f 0x6d,对应十进制84 111 109,与1818581860的字节序相关(小端存储)。
继续执行到第二个断点:
(gdb) continue
(gdb) break var_demo.c:22
(gdb) continue
此时再次查看变量,观察变化:
(gdb) print count
$8 = 5
(gdb) print arr[2]
$9 = 99
(gdb) print msg
$10 = "Changed"
(gdb) print stu.score
$11 = 95
验证方法与判定标准
- 在第一个断点处,
print输出的变量值与源码中初始化值一致:count=3、arr[2]=30、msg="GDB-Demo"、stu.id=1001。 x命令显示的内存内容与print得到的变量值一致(注意字节序和数据类型宽度)。- 执行到第二个断点后,
print显示的值与修改后的赋值一致:count=5、arr[2]=99、msg="Changed"、stu.score=95。 - 通过
print &变量名能获得变量地址,且该地址与x命令使用的地址一致。
常见问题
- 地址每次运行不同:ASLR(地址空间布局随机化)导致每次运行时栈地址变化,但GDB中
print &var给出的地址始终是当前进程的有效地址,直接使用即可。 - x命令格式:
x/nfu addr中n是重复次数,f是显示格式(d十进制、x十六进制、c字符、s字符串、f浮点),u是单位大小(b单字节、h双字节、w四字节、g八字节)。 - 结构体内存布局:由于对齐,结构体字段之间可能有填充字节,直接查看原始内存时可能看到非直观数值,建议结合
print命令确认字段值。