代码示例
首先,创建一个简单的链表程序 linked_list.c
,以演示如何使用 gdb
查看内存中的数据结构。
#include <stdio.h>
#include <stdlib.h>
// 定义链表节点结构体
typedef struct Node {
int data;
struct Node* next;
} Node;
// 添加新节点到链表的尾部
void append(Node** head_ref, int new_data) {
Node* new_node = (Node*)malloc(sizeof(Node));
Node* last = *head_ref;
new_node->data = new_data;
new_node->next = NULL;
// 如果链表为空,新节点成为头节点
if (*head_ref == NULL) {
*head_ref = new_node;
return;
}
// 否则,遍历到链表的末尾,并添加新节点
while (last->next != NULL) {
last = last->next;
}
last->next = new_node;
}
// 打印链表的所有节点
void print_list(Node* node) {
while (node != NULL) {
printf("%d -> ", node->data);
node = node->next;
}
printf("NULL\n");
}
int main() {
Node* head = NULL;
append(&head, 1);
append(&head, 2);
append(&head, 3);
print_list(head);
// 等待用户输入,以便在 gdb 中调试
getchar();
return 0;
}
编译程序
使用 -g
标志编译程序,以便生成调试信息:
gcc -g -o linked_list linked_list.c
使用 gdb
进行调试
-
启动
bashgdb
:gdb ./linked_list
-
设置断点:在
gdbmain
函数的入口处设置断点:(gdb) break main
-
运行程序:开始运行程序,直到程序暂停在
gdbmain
函数的入口处:(gdb) run
-
逐行执行:当断点命中时,逐行执行程序代码,直到到达定义
gdbhead
变量的位置:(gdb) n # 逐行执行,直至到达定义 'head' 变量的位置
-
打印
gdbhead
变量:在正确的上下文中打印head
变量的值:(gdb) p head
这将输出
gdbhead
变量的地址,例如:$1 = (Node *) 0x5555555592a0
-
检查链表节点:打印链表的节点数据。假设
gdbhead
是链表的头节点,可以打印它及其后续节点的内容:(gdb) p *head # 打印 head 节点的数据 (gdb) p *(head->next) # 打印下一个节点的数据 (gdb) p *(head->next->next) # 打印下下一个节点的数据
输出示例:
gdb$2 = {data = 1, next = 0x5555555592c0} $3 = {data = 2, next = 0x5555555592e0} $4 = {data = 3, next = 0x0}
总结
- 编译程序:确保使用
-g
标志编译程序。 - 启动
gdb
:使用gdb
附加到程序。 - 设置断点:在
main
函数的入口处设置断点。 - 运行程序:运行程序并在断点处停止。
- 逐行执行:逐行执行程序,直至访问
head
变量。 - 打印和检查变量:打印
head
和链表节点的数据。
通过以上步骤,你可以在 gdb
中成功查看和调试进程内存中的数据结构。