gdb/cgdb调试技巧加餐

示例代码

cpp 复制代码
#include <stdio.h>

int Sum(int s, int e)
{
    int result = 0;
    for (int i = s; i <= e; i++)
    {
        result += i;
    }
    return result;
}

int main()
{
    int start = 1;
    int end = 100;
    printf("I will begin\n");
    int n = Sum(start, end);
    printf("running done, result is: [%d-%d]=%d\n", start, end, n);
    return 0;
}

使用watch命令监视变量

假设我们想要监视Sum函数中result变量的变化,以确保它正确地累加了从startend的所有整数。

  1. 编译并启动GDB

    gcc -g -o mycmd mycmd.c
    cgdb mycmd
    
  2. 查看main函数的代码并设置断点

    (gdb) l main  # 查看main函数的代码,确定在哪里设关卡
    (gdb) b 20    # 在第20行设关卡,这里是程序调用Sum函数的地方
    
  3. 运行程序并进入Sum函数

    (gdb) r       # 让程序开始运行
    (gdb) s       # 进入Sum函数
    
  4. 设置监视点并继续执行

    (gdb) n       # 执行下一步,到达变量result声明的地方
    (gdb) watch result  # 在result变量上安装摄像头,监视它的值
    (gdb) c       # 继续运行程序,等待摄像头警报
    
  5. 观察变量变化 每当result的值发生变化时,GDB会暂停程序并通知你。你可以继续使用c命令来查看result的下一个变化。

   (gdb) c       # 再次继续,查看下一个变化
   (gdb) c       # 继续这个过程,观察result的变化

删除的时候就和删除断点一样。
注意:
如果你有⼀些变量不应该修改,但是你怀疑它修改导致了问题,你可以watch它,如果变化了,就会通知你。

使用set var命令确定问题原因

假设我们在Sum函数中添加了一个全局变量flag,并且我们怀疑flag的值可能影响了Sum函数的结果。

  1. 修改代码并重新编译

    cpp 复制代码
    int flag = 0; // 故意设置一个可能影响结果的变量
    
    int Sum(int s, int e)
    {
        int result = 0;
        for (int i = s; i <= e; i++)
        {
            result += i;
        }
        return result * flag; // 使用flag影响结果
    }
  2. 重新编译并启动GDB

    gcc -g -o sum_program sum_program.c
    gdb ./sum_program
    
  3. 设置断点并运行程序

    (gdb) l main  # 查看main函数的代码
    (gdb) b 20    # 在第20行设关卡
    (gdb) r       # 让程序开始运行
    
  4. 进入Sum函数并快速执行到末尾

    (gdb) s       # 进入Sum函数
    (gdb) until 14  # 快速执行到函数末尾,也就是return语句前
    (gdb) p result   # 查看result变量的值
    (gdb) p flag     # 查看flag变量的值
    
  5. 修改flag的值并继续执行

    (gdb) set var flag=1  # 替换零件,把flag的值改为1
    (gdb) p flag          # 确认零件(flag的值)已经替换成功
    (gdb) n               # 继续执行下一步
    (gdb) n               # 再执行一步,看看机器(程序)的反应
    

我们能使用set var来进行变量值的临时的调整。

使用条件断点

假设我们想要在Sum函数的循环中,只在i等于30时暂停程序,以检查此时的result值。

  1. 设置普通断点并运行程序

    (gdb) l main  # 查看main函数的代码
    (gdb) b 20    # 在第20行设普通关卡
    (gdb) r       # 让程序开始运行
    
  2. 进入Sum函数并设置条件断点

    (gdb) s       # 进入Sum函数
    (gdb) n       # 执行下一步,到达循环开始的地方
    (gdb) b 9 if i == 30  # 在第9行设条件断点,只在i等于30时暂停
    
  3. 查看断点信息并继续执行

    (gdb) info b  # 查看所有断点信息,确认条件断点已经设置
    (gdb) finish  # 让Sum函数执行完,看看结果
    (gdb) finish  # 再次使用finish,回到main函数
    
  4. 给已有断点追加条件 假设我们已经设置了一个普通断点,现在想要给它追加条件。

    (gdb) b 9     # 先设一个普通关卡(普通断点)
    (gdb) info b  # 查看所有断点信息,找到刚刚设的关卡编号
    (gdb) condition 2 i==30  # 给编号为2的关卡追加条件,只在i等于30时暂停
    (gdb) info b  # 再次查看所有断点信息,确认条件已经追加成功
    (gdb) c       # 让程序继续运行,直到满足条件的关卡拦下来
    (gdb) p i     # 当程序因条件断点暂停时,查看变量i的值
    (gdb) p result  # 查看此时result变量的值
    

注意事项

  • 使用watch命令 :如果你有一些变量不应该被修改,但怀疑它们被修改导致了问题,可以使用watch命令在这些变量上安装"摄像头"。一旦这些变量的值发生变化,GDB会暂停程序并通知你。
  • 条件断点 :条件断点有两种常见添加方式:
    • 新增条件断点 :在设置断点时直接添加条件,例如 b 9 if i == 30
    • 给已有断点追加条件 :先设置一个普通断点,然后使用condition命令给它追加条件,例如 condition 2 i==30。注意,这里的2是断点的编号,可以通过info b命令查看。

通过这些步骤,你可以更有效地使用GDB来调试程序,找到并修复隐藏在代码中的问题。希望这些解释和示例能帮助你更好地理解和使用GDB。

相关推荐
是店小二呀2 小时前
【Linux】从零开始:编写你的第一个Linux进度条小程序
linux·运维·小程序
chian-ocean3 小时前
进程的家园:探索 Linux 地址空间的奥秘
android·java·linux
学习嵌入式的小羊~3 小时前
RV1126+FFMPEG推流项目(3)VI模块视频编码流程
linux·音视频
搬码后生仔3 小时前
x86-64架构的Linux服务器上运行.NET 6.0应用程序,安装runtimes
linux·服务器·.net
非凡的世界9 小时前
linux命令行连接Postgresql常用命令
linux·数据库·postgresql
惟长堤一痕12 小时前
黑马linux入门笔记(01)初始Linux Linux基础命令 用户和权限 实用操作
linux·运维·笔记
lida200313 小时前
Open FPV VTX开源之默认MAVLink设置
linux·ardupilot·openipc·diy drone
CAD芯智库14 小时前
国产信创3D- 中望3D Linux 2025发布,助力企业高效转型国产三维CAD
linux·运维·3d