实例:使用 gdb 查看进程内存中的数据结构

代码示例

首先,创建一个简单的链表程序 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 标志编译程序,以便生成调试信息:

bash
gcc -g -o linked_list linked_list.c

使用 gdb 进行调试

  1. 启动 gdb

    bash
    gdb ./linked_list
  2. 设置断点:在 main 函数的入口处设置断点:

    gdb
    (gdb) break main
  3. 运行程序:开始运行程序,直到程序暂停在 main 函数的入口处:

    gdb
    (gdb) run
  4. 逐行执行:当断点命中时,逐行执行程序代码,直到到达定义 head 变量的位置:

    gdb
    (gdb) n # 逐行执行,直至到达定义 'head' 变量的位置
  5. 打印 head 变量:在正确的上下文中打印 head 变量的值:

    gdb
    (gdb) p head

    这将输出 head 变量的地址,例如:

    gdb
    $1 = (Node *) 0x5555555592a0
  6. 检查链表节点:打印链表的节点数据。假设 head 是链表的头节点,可以打印它及其后续节点的内容:

    gdb
    (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}

总结

  1. 编译程序:确保使用 -g 标志编译程序。
  2. 启动 gdb:使用 gdb 附加到程序。
  3. 设置断点:在 main 函数的入口处设置断点。
  4. 运行程序:运行程序并在断点处停止。
  5. 逐行执行:逐行执行程序,直至访问 head 变量。
  6. 打印和检查变量:打印 head 和链表节点的数据。

通过以上步骤,你可以在 gdb 中成功查看和调试进程内存中的数据结构。

posted @ 2024-09-09 11:35  若-飞  阅读(211)  评论(0)    收藏  举报