使用watch来监控内存

众所周知,在所有的逻辑Bug中,野指针或者数组越界引起的Bug最难调,因为暴露问题的地方与真正产生问题的地方往往不是在同一个地方,而且这种Bug往往具有随机性,让人头痛。

调上述Bug的标准做法就是使用GDB的watch命令来监控内存变化,当watch的内存发生变化时,调试程序会停住,我们就知道是哪一步动了“奶酪”。

watch的使用也很简单,如果有一个指针pTest指向一块内存,则:

  • watch pTest 监控pTest指针变量本身,如果pTest中存储的内存地址发生变化,调试程序停住
  • watch *pTest 监控pTest所指向的内存(*pTest本身就是一个地址数据),如果这块内存发生变化,调试程序停住

其中watch *pTest的形式往往更常用

但在使用watch的时候会常常遇到如下问题:

https://stackoverflow.com/questions/4702638/gdb-watch-pointer-giving-too-many-h-w-watchpoints-error

https://stackoverflow.com/questions/3470704/setting-gdb-hardware-watchpoint-how-to-set-software-watchpoint

(gdb) watch val_msgs[0]->val
Hardware watchpoint 2: this->val_msgs[0]->val
(gdb) c
Continuing.
pingCharmrun (ignored=0x7ffff73751c1) at machine.c:1151
1151    {
Current language:  auto; currently c
(gdb) c
Continuing.
Warning:
Could not insert hardware watchpoint 2.
Could not insert hardware breakpoints:
You may have requested too many hardware breakpoints/watchpoints.

最后一行说设置了太多硬件断点或者watch点,但实际上只设置了一个watch点,这其实是调试寄存器不够用造成的,有如下两种方案可以解决:

  1. 减少监控对象。我发现可以用全局指针来指向想监控的内存,然后watch全局指针,这样就不会报错,但是并不明白其中原理。
  2. 其实也不用这么麻烦,标准解决方案是在GDB中:
    set can-use-hw-watchpoints 0

    就是将硬件watch点设置为0,这样GDB会使用软件watch点,这当然比硬件watch点要慢,但是不影响GDB使用,更重要的是watch点可以放开用了。

你可能感兴趣的:(C++,Linux基本操作,操作系统)