引言

C代码中经常会有大量的指针在很多不同函数中传来传去,甚至还有强制类型转换,让阅读代码和调试BUG的人苦不堪言。更有甚者将全局变量指针赋值给局部变量,然后再作为参数传出并修改。

这是官网的说明:http://sourceware.org/gdb/current/onlinedocs/gdb/Set-Watchpoints.html#Set-Watchpoints

说明

watch是gdb众多命令中的一个,用来检测变量,当被监测的变量被修改时,会自动中断程序,此时用户就可以看到变量在哪里被修改了。

我们都知道,C中的变量是有生命周期的,很显然,watch只能在变量的生命周期内进行监测,这一点一定要注意。很容易想通,变量存储在内存或者寄存器中,既然还没创建或者已经释放了,还怎么监测呢?

由上可以得出:

1.全局区:全局变量生命周期和整个程序一样,可以在初始化后进行watch;

2.堆区:在被创建和释放前都可以watch;

3.栈区:只能在函数内部watch

理解了上面的3点,就可以开心的使用watch了。

注意

注意事项:watch的断点分为硬断点和软断点,硬断点需要机器硬件支持,不仅速度快,而且断点可以精确到汇编指令级别。

不同于break断点,生命周期结束后,watch断点会自动删除。

开启硬断点的方法:set can-use-hw-watchpoints 1

下面是用来演示的代码,功能很简单,只是一些赋值。

#include<stdio.h>
#include<stdlib.h>
#include<string.h>
typedef struct INFO
{int age;char *name;
}ST_INFO;//全局区
ST_INFO gInfo;void set_name()
{char *name = (char*)malloc(20 * sizeof(char));strcpy(name, "hey suse");gInfo.name = name;
}
void set_age()
{gInfo.age = 22;
}void motify(ST_INFO *pInfo)
{pInfo->name = "motify";pInfo->age = 66;
}int main()
{//malloc后存储在堆区ST_INFO *pInfo = NULL;//存储在栈区ST_INFO info;info.name = "hello";info.age = 35;pInfo = (ST_INFO*)malloc(sizeof(ST_INFO));pInfo->name = "malloc";pInfo->age = 108;motify(pInfo);free(pInfo);set_age();set_name();pInfo = &gInfo;motify(pInfo);return 0;}

全局

设置观测点

(gdb) watch gInfo.name
Hardware watchpoint 1: gInfo.name

可以看到提示是硬断点了

(gdb) r
The program being debugged has been started already.
Start it from the beginning? (y or n) y
Starting program: /home/luogf/20210815/a.out
Hardware watchpoint 1: gInfo.nameOld value = 0x0
New value = 0x601010 "hey suse"
set_name () at watch.c:17
17  }
(gdb) bt
#0  set_name () at watch.c:17
#1  0x000000000040062f in main () at watch.c:46

运行后程序在修改点停了下来,可以看到修改前的值Old value = 0x0,以及修改后的值New value = 0x601010 "hey suse";在set_name函数里修改了全局的name。

(gdb) c
Continuing.
Hardware watchpoint 1: gInfo.nameOld value = 0x601010 "hey suse"
New value = 0x400751 "motify"
motify (pInfo=0x600aa0) at watch.c:26
26      pInfo->age = 66;

这里将全局的地址赋值给了一个局部变量,然后在motify中修改,试想再多传几次,想要通过看代码去分析,大工程的代码能累死人。。。

堆区

(gdb) watch pInfo
No symbol "pInfo" in current context.

直接watch发现不行,因为此时pInfo还没创建呢,你需要先在pInfo创建后再watch才能成功。

(gdb) b 37
Breakpoint 8 at 0x4005df: file watch.c, line 37.
(gdb) r
Starting program: /home/luogf/20210815/a.out Breakpoint 8, main () at watch.c:37
37      pInfo = (ST_INFO*)malloc(sizeof(ST_INFO));
(gdb) watch pInfo.name
Hardware watchpoint 9: pInfo.name

pInfo没有开辟空间依然可以watch,下面在malloc时停了下来,初始值时0。

(gdb) c
Continuing.
Hardware watchpoint 9: pInfo.nameOld value = <unreadable>
New value = 0x0
main () at watch.c:38
38      pInfo->name = "malloc";
(gdb) i b
Num     Type           Disp Enb Address            What
8       breakpoint     keep y   0x00000000004005df in main at watch.c:37breakpoint already hit 1 time
9       hw watchpoint  keep y                      pInfo.namebreakpoint already hit 1 time

继续运行,修改了两次值,最后通过free释放,值变成了随机。

(gdb) c
Continuing.
Hardware watchpoint 9: pInfo.nameOld value = 0x0
New value = 0x40075e "malloc"
main () at watch.c:39
39      pInfo->age = 108;
(gdb) c
Continuing.
Hardware watchpoint 9: pInfo.nameOld value = 0x40075e "malloc"
New value = 0x400751 "motify"
motify (pInfo=0x601010) at watch.c:26
26      pInfo->age = 66;
(gdb) c
Continuing.
Hardware watchpoint 9: pInfo.nameOld value = 0x400751 "motify"
New value = 0x400700 "H\203\370\377t\031\273\210\b`"

由于将pInfo指向了全局gInfo,这两个已经是一个值了,后面gInfo变化也会触发断点。

(gdb) c
Continuing.
Hardware watchpoint 9: pInfo.nameOld value = 0x400700 "H\203\370\377t\031\273\210\b`"
New value = 0x601010 "hey suse"
main () at watch.c:50
(gdb) p pInfo
$1 = (ST_INFO *) 0x600aa0
(gdb) p &gInfo
$2 = (ST_INFO *) 0x600aa0
(gdb) c
Continuing.
Hardware watchpoint 9: pInfo.nameOld value = 0x601010 "hey suse"
New value = 0x400751 "motify"
motify (pInfo=0x600aa0) at watch.c:26
26      pInfo->age = 66;
(gdb) c
Continuing.
Hardware watchpoint 9: pInfo.nameOld value = 0x601010 "hey suse"
New value = 0x400751 "motify"
motify (pInfo=0x600aa0) at watch.c:26
26      pInfo->age = 66;
(gdb) c
Continuing.Watchpoint 9 deleted because the program has left the block in
which its expression is valid.
0x00007ffff7a66d20 in __libc_start_main () from /lib64/libc.so.6
(gdb) i b
Num     Type           Disp Enb Address            What
8       breakpoint     keep y   0x00000000004005df in main at watch.c:37breakpoint already hit 1 time
(gdb)

生命周期结束后,watch断点会自动删除

栈区

和堆区差不多,不过只能在函数内部查看。

Breakpoint 6, main () at watch.c:31
31      ST_INFO *pInfo = NULL;
(gdb) watch info.name
Hardware watchpoint 9: info.name
(gdb) c
Continuing.
Hardware watchpoint 9: info.nameOld value = 0x400470 "1\355I\211\321^H\211\342H\203\344\360PTI\307\300P\006@"
New value = 0x400758 "hello"

使用GDB中的watch来调试指来指去的指针相关推荐

  1. GDB中应该知道的几个调试方法

     七.八年前写过一篇< 用GDB调试程序>,于是,从那以后,很多朋友在MSN上以及给我发邮件询问我关于GDB的问题,一直到今天,还有人在问GDB的相关问题.这么多年来,有一些问题是大家 ...

  2. 【转贴】gdb中的信号(signal)相关调试技巧

    一篇不错的帖子,讲的是gdb中的信号(signal)相关调试技巧 转自Magic C++论坛  http://www.magicunix.com/index_ch.html  http://www.m ...

  3. GDB中应该知道的几个调试方法-转

    七.八年前写过一篇<用GDB调试程序>,于是,从那以后,很多朋友在MSN上以及给我发邮件询问我关于GDB的问题,一直到今天,还有人在问GDB的相关问题.这么多年来,有一些问题是大家反复在问 ...

  4. linux问号符号,调试linux内核时gdb中的问号符号4.10

    我想从linux内核中的函数start_kernel()调试linux内核.调试linux内核时gdb中的问号符号4.10 这基本上就是我已经做了 从kernel.org 下载4.10内核源提取源后: ...

  5. gdb中的信号(signal)相关调试技巧

    一篇不错的帖子,讲的是gdb中的信号(signal)相关调试技巧 转自Magic C++论坛 http://www.magicunix.com/index_ch.html http://www.mag ...

  6. gdb 的用法(Linux调试器)

    在Linux应用程序开发中,最常用的调试器是gdb,它可以在程序中设置断点.查看变量值.一步一步跟踪程序的执行过程. GDB(GNU symbolic debugger)简单地说就是一个调试工具.它是 ...

  7. 嵌入式开发中使用DDD进行调试

    在嵌入式程序开发过程中,程序员要进行大量的调试,以此验证程序的正确性,修改潜在的错误.调试器对于程序员来说是不可或缺的必备工具.在Linux环境中,有很多调试工具和调试辅助工具,例如GDB.XXGDB ...

  8. linux下 如何调试php,linux下使用gdb对php源码调试

    title: linux下使用gdb对php源码调试 date: 2018-02-11 17:59:08 tags: --- linux下使用gdb进行php调试 调试了一些php的漏洞,记录一下大概 ...

  9. gdb tui 安装_GDB 单步调试汇编

    之前在看汇编的时候一直是肉眼看GCC -S的结果,缺点是很不直观,无法实时的看到寄存器的值,所以研究了下如何用GDB调试汇编.当然,写这篇文章更重要的一个目的是半年没有写博客了,博客要长草了.^_^ ...

最新文章

  1. Apache Beam 是什么,它为什么比其他选择更受欢迎?
  2. Python小游戏(贪吃蛇)
  3. Hibernate 笔记 缓存
  4. 破坏计算机系统既遂的标准,破坏计算机信息系统罪的量刑标准是什么
  5. 查看nginx php mysql apache编译安装参数
  6. [JAVA基础]你知道Java的四种引用类型吗
  7. pycharm和jupyter notebook中的快捷键
  8. 软件测试基本功 系列教程
  9. 一种视频录制时,类似监控视频中加入动态时间标记的装置
  10. PaddlePaddle (飞桨) - 开源深度学习平台
  11. PS176替代方案| DP转HDMI2.0音视频转换芯片CS5263
  12. VGG 图像打标签工具
  13. 窗帘可以选择这6种效果不错的颜色 - 好佳居窗帘十大品牌
  14. unity 陶瓷质感_Unity2D:简单自动瓷砖(Tile)的实现
  15. JavaScript知识之正则表达式(RegExp)
  16. 格鲁夫给经理人的第一课
  17. Selenium 自动化测试从零实战
  18. WPF加载obj模型-2
  19. 数据安全入门产品——数据库审计系统详解
  20. 频谱仪 网口LAN 数据导出

热门文章

  1. Excel 表格如何设置时间提前提醒,并且变化颜色
  2. 关于戴尔电脑频繁屏幕卡死问题的自我研究
  3. 坐标成都!百度AI快车道与网红城市的“新耍法”你期待吗
  4. Xcode7.3 真机测试 ,添加iOS10的idk到Xcode7.3中
  5. 《深度学习推荐系统》学习笔记(5)——Embedding(论文)
  6. 注册页面(CSS)效果图+代码
  7. 转:意识的成长,是为了看见生命的真相
  8. word 技巧之一:给word文档添加目录、查看word文档结构图
  9. 2021-12-05 vue移动端卖座电影项目(六) 为详情页面Detail.vue获取后台数据并设置样式
  10. 有什么好用的翻译外文工具?快来看看这个方法吧