GDB watch 变量

        最近工作当中遇到一个问题,在函数调用过程中返回错误了,但那个函数里if分支相当多,而且还调用了其他很多的函数,就是函数调用层级太深了,在没有日志输出的情况下根本无法判断到底是哪个函数返回错误了,于是 gdb 的 watch 派上了用场。

        watch 必须要和断点一起使用,没有断点的话 watch 什么呢,而且很多情况下你要 watch 的是一个局部范围内的变量。

watch_break_pointer.cpp

#include <stdio.h>
#include <stdlib.h>

extern int initConfig();
extern int setConfig();
extern int getConfig();

int getLocalConfig();

int main()
{
    getLocalConfig();
    return 0;
}

int getLocalConfig()
{
    int ret = 0;
    ret |= initConfig();
    ret |= setConfig();
    ret |= getConfig();
    
    return ret;
}

configManager.cpp

#include <stdio.h>
#include <stdlib.h>


int initConfig()
{
    return 0;
}

int setConfig()
{
    return -1;
}

int getConfig()
{
    return 0;
}

可以看到,如果设置了断点,然后就设置 watch 是没用的,而当断点被触发时再设置 watch 点则可以看出,它是基于调用栈帧的,如:

这个 断点是在函数的入口处,只有当断点触发时才能设置 watch 点。而当 watch 变量值发生变化时,程序则停止执行,所以我们需要输入 c 继续往下执行。

当继续往下执行后,ret 值发生了变化,程序停在了 watch_break_pointer.cpp 21 行处,这表明在这行之前 ret 发生了变化,因为函数在返回给 ret 后 gdb 才检测到 ret 发生变化,所以停在了变化的下一行准备继续执行。上面我们讲到 watch 是基于调用栈帧的,那从哪里可以得出这样的结论呢?刚才我们 watch 了一个函数入口处的变量,那如果我们 watch 一个函数里的变量呢?是否会成功呢?

#include <stdio.h>
#include <stdlib.h>

extern int initConfig();
extern int setConfig();
extern int getConfig();

int getLocalConfig();

int main()
{
    getLocalConfig();
    return 0;
}

int getLocalConfig()
{
    int ret = 0;
    ret |= initConfig();
    ret |= setConfig();
    ret |= getConfig();

    int rt = 0;
    rt = setConfig();
    
    return ret;
}

发现了程序被停止了 2 次,因为我们在函数入口 watch rt,此时 rt 应该是一个随机值,当程序执行到 rt = 0 时程序被停止,再往下执行时 rt = -1 再被停止。当我把断点断在函数内部时也是可以设置watch 的,如:

 但是变量 ret 在21行后是没有发生变化的,所以不会有 ret 值变化的断点触发。所以 watch 是基于是调用栈帧的,而调用栈帧其实也就是函数调用。所以当你要设置 watch 时,就要看你把断点断在哪里了。 

  • 0
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值