gdb 内存断点watch 的使用

1.  watch 变量的类型
    a. 整形变量: int i; watch i;
    b. 指针类型:  char *p; watch p, watch *p;
    它们是有区别的.
      watch p 是查看 *(&p), 是p 变量本身。

      watch (*p) 是 p 所指的内存的内容, 查看地址,一般是我们所需要的。

      我们就是要看某地址上的数据是怎样变化的,虽然这个地址具体位置只有编译器知道。

    c. watch 一个数组或内存区间
    char buf[128], watch buf,  
    是对buf 的128个数据进行了监视. 此时不是采用硬件断点,而是软中断实现的。
    软中断方式去检查内存变量是比较耗费cpu资源的。
    精确的指明地址是硬件中断。

2. 当你设置的观察点是一个局部变量时。局部变量无效后,观察点无效
 Watchpoint 2 deleted because the program has left the block in
  which its expression is valid.
               
3. 附上一个简单程序方便你利用内存断点观察,调试.
 

$ cat test.cpp
#include <stdio.h>
#include <string.h>
void initBuf(char *buf);
void prtBuf(char *buf);
char mem[8];
char buf[128];
int main()
{
	initBuf(buf);
	prtBuf(buf);
	return 0;
}

void initBuf(char *pBuf)
{
	int i, j;
	mem[0]='0';
	mem[1]='1';
	mem[2]='2';
	mem[3]='3';
	mem[4]='4';
	mem[5]='5';
	mem[6]='6';
	mem[7]='7';
	//ascii table first 32 is not printable
	for(i=2;i<8;i++)
	{
		for(j=0;j<16;j++)
			pBuf[i*16+j]=i*16+j;
	}
}

void prtBuf(char *pBuf)
{
	int i, j;
	for(i=2;i<8;i++)
	{
		for(j=0;j<16;j++)
			printf("%c  ", pBuf[i*16+j]);
		printf("\n");
	}
}


玩弄内存调试于股掌之中。
(由于效率问题你需要适当控制内存断点设置,当然,对这个小程序无所谓.)
----------------------------------------
看一下mem 数组, 内存数据是怎样被写入的。
----------------------------------------
gdb test
b main
watch mem
run
Breakpoint 1, main () at test.cpp:9
gdb) continue
  Continuing.
  Hardware watchpoint 2: mem
  Old value = "\000\000\000\000\000\000\000"
  New value = "0\000\000\000\000\000\000"
  initBuf (pBuf=0x6010a0 <buf> "") at test.cpp:18
(gdb) continue
  Continuing.
  Hardware watchpoint 2: mem
  Old value = "0\000\000\000\000\000\000"
  New value = "01\000\000\000\000\000"
  initBuf (pBuf=0x6010a0 <buf> "") at test.cpp:19
(gdb) continue
  Continuing.
  Hardware watchpoint 2: mem
  Old value = "01\000\000\000\000\000"
  New value = "012\000\000\000\000"
  initBuf (pBuf=0x6010a0 <buf> "") at test.cpp:20
(gdb)
......

(gdb) continue
  Continuing.
  Hardware watchpoint 2: mem
  Old value = "0123456"
  New value = "01234567"
  initBuf (pBuf=0x6010a0 <buf> "") at test.cpp:26
 

使用watch时出现错误:
----------------------------------------
Could not insert hardware breakpoints: You may have requested too many hardware breakpoints/watchpoints.
你watch的变量超过了硬件能监控的范围。
原因1:
你设置的watchpoints数量过多,系统一般只支持4个,
原因2:
你监控一个结构/类成员也可能出现这个问题。因为结构太大了.尽管你只是监控了其中一个变量,但gdb按整个结构算.

解决方法:
----------------------------------------
直接获取你所要监控变量的地址, 监控这个地址.
例如: 监视一个4byte 的整形地址. 书写格式举例如下.
watch *(int*)0x12345678

<think>好的,我需要帮助用户了解如何在C++使用GDB设置断点。首先,用户之前的问题是关于查看可执行程序符号表的方法,现在转向断点设置,这可能是因为他们在调试过程中遇到了符号相关的问题,或者需要更深入的调试技巧。 用户提供的引用内容提到了断点设置的不同方法,包括按线程、函数名、行号、条件和正则表达式设置断点,以及查看和管理断点的方法。我需要将这些信息整合成一个结构清晰的教程,确保涵盖基本和高级用法。 首先,我需要确定用户可能的背景。他们可能是有一定C++编程经验的开发者,但在使用GDB进行调试时遇到困难,特别是在设置断点方面。可能需要从基础开始,逐步介绍各种断点设置方法,同时结合实际示例,让用户更容易理解。 接下来,我需要组织内容。通常,教程的结构应该从简单到复杂。先介绍基本断点设置,如函数名和行号,然后是条件断点、临时断点,再是高级功能如线程特定断点和正则表达式匹配。最后,讲解如何管理断点,比如查看、删除、禁用等。 同时,用户提供的引用中提到了一些具体命令,如`break main`、`b 9`、`condition`等,这些需要详细解释,并给出示例。还要注意GDB版本可能带来的差异,但假设用户使用的是较新版本,兼容这些命令。 另外,用户可能遇到的一些常见问题,比如断点不生效,可能的原因是什么,如何排查,比如检查符号是否正确加载,编译时是否包含调试信息(-g选项)。这些也需要在教程中提及,帮助用户避免常见陷阱。 还需要考虑用户可能的应用场景,比如多线程调试,这时候设置线程特定断点就很有用。或者调试大型项目时,使用正则表达式设置多个断点,提高效率。 最后,确保语言简洁明了,步骤清晰,每个部分都有示例代码和解释,方便用户跟随操作。可能还需要提示一些实用技巧,比如使用`info breakpoints`查看断点状态,使用`disable`和`enable`管理断点,以及如何保存断点配置等。 总结来说,我需要将用户提供的引用内容整合成一个全面的GDB断点设置教程,涵盖基本到高级功能,结合实际示例和常见问题解决方案,确保用户能够有效应用这些技巧进行C++程序的调试。</think>### C++项目中使用GDB设置断点的完整指南 --- #### **一、基础断点设置** ##### 1. 按函数名设置断点 ```gdb (gdb) break main # 在main函数入口设置断点 (gdb) b MyClass::method # 在类的成员函数设置断点 (gdb) b namespace::func # 在命名空间函数设置断点[^1] ``` *示例调试STL容器:* ```gdb (gdb) b std::vector<int>::push_back # 跟踪vector的插入操作 ``` ##### 2. 按行号设置断点 ```gdb (gdb) b 20 # 当前文件第20行 (gdb) b src/utils.cpp:45 # 指定文件的特定行[^3] ``` *验证符号加载:* ```gdb (gdb) info line src/utils.cpp:45 # 查看该行是否关联有效代码 ``` ##### 3. 按地址设置断点 ```gdb (gdb) b *0x401550 # 在内存地址设置断点 (gdb) b *&global_var # 在全局变量地址设置访问断点 ``` --- #### **二、高级断点控制** ##### 1. 条件断点(重点功能) ```gdb (gdb) b 35 if count > 100 # 基本条件判断 (gdb) b MyClass::validate() if ptr==0 # 结合类成员变量 (gdb) condition 2 (x%2)==0 # 修改2号断点的条件[^3] ``` *复杂条件示例:* ```gdb (gdb) b 89 if (strcmp(buffer,"ERROR")==0) && (errno == EINVAL) ``` ##### 2. 临时断点(单次触发) ```gdb (gdb) tbreak 15 # 触发一次后自动删除 (gdb) tbreak init_system if !initialized # 配合初始化状态检测 ``` ##### 3. 线程特定断点 ```gdb (gdb) b worker.cpp:33 thread 2 # 仅在2号线程生效 (gdb) b mutex_lock thread 1-4 # 在1-4号线程生效[^1] ``` --- #### **三、智能断点策略** ##### 1. 正则表达式批量设置 ```gdb (gdb) rbreak MyFactory::create* # 匹配所有create开头的方法 (gdb) rbreak .*::validate # 匹配所有类的validate方法[^3] ``` ##### 2. 观察点(数据断点) ```gdb (gdb) watch global_counter # 变量写入时中断 (gdb) watch *(int*)0x7fffffffe314 # 监控指定内存地址 (gdb) awatch buffer_ptr # 读写时均中断(访问观察点) ``` ##### 3. 事件断点 ```gdb (gdb) catch throw # 捕获所有异常抛出 (gdb) catch syscall open # 拦截系统调用 (gdb) catch fork # 跟踪进程分叉事件 ``` --- #### **四、断点管理技巧** ##### 1. 断点状态查看 ```gdb (gdb) info break [n] # 查看所有/指定断点 (gdb) i b # 简写命令 ``` *典型输出解析:* ``` Num Type Disp Enb Address What 1 breakpoint keep y 0x000055555555516a in main() at demo.cpp:8 breakpoint already hit 3 times cond 1 (x > 100) # 显示附加条件 ``` ##### 2. 断点维护操作 ```gdb (gdb) disable 3-5 # 禁用3-5号断点 (gdb) enable once 2 # 仅启用2号断点一次 (gdb) ignore 4 10 # 忽略4号断点前10次触发 (gdb) save breakpoints bp.conf # 保存断点配置[^2] ``` ##### 3. 断点自动执行命令 ```gdb (gdb) commands 2 > print buffer[0] > backtrace > continue > end ``` --- #### **五、调试场景示例** ##### 案例:多线程数据竞争调试 ```gdb (gdb) b worker_thread() thread 3 if shared_flag # 特定线程条件断点 (gdb) watch -l shared_data # 监控共享数据变化 (gdb) set scheduler-locking step # 调试时锁定其他线程 ``` ##### 案例:STL容器异常分析 ```gdb (gdb) b __throw_bad_alloc # 捕获内存分配异常 (gdb) b std::vector<int>::_M_range_check # 越界访问检测 ``` --- ### 常见问题排查 1. **断点显示但未触发** - 检查编译时是否包含`-g`选项:`objdump --dwarf=info program | grep DW_TAG_compile_unit` - 验证代码优化级别:`-O0`确保代码未被优化删除 2. **条件断点性能低下** 使用硬件观察点提升速度: ```gdb (gdb) hbreak 45 if x>100 # 硬件辅助断点 ``` 3. **动态库断点失效** 强制加载符号: ```gdb (gdb) set stop-on-solib-events 1 (gdb) run # 当库加载时暂停 (gdb) sharedlibrary # 重新加载符号 ``` --- [^1]: GNU调试器手册-断点设置章节 [^2]: GDB官方文档-断点保存与恢复 : ELF调试技术深度解析
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值