GDB觀察點watchpoints的介紹和演示


image

watchpoint介紹

watchpoint(觀察點):
很多情況下,程序的bug是由於某個變量或地址被莫名修改而導致的,但是具體什么時候修改了該值,我們很難定位到。使用傳統的方法只能一步一步去調試跟蹤程序,傷神費力,調試效率特別低。

gdb提供了觀察點watchpoint功能,可以監控程序中變量或表達式的值,只要在運行過程中發生改變,程序就會停止執行。可以說學會watchpoint,能夠實現讓bug自動現身的效果。

觀察點適用場景:

  • 由於變量值異常變化導致的bug。
  • 確定了某個異常變量,但是該變量被多次使用、還會在各種循環內被操作。
  • 多線程場景,線程切來切去,不知道變量具體被哪個線程修改了。

watchpoint命令

命令 含義
watch a 觀察變量a
watch a*b+c 觀察表達式a*b+c
watch *0x123456 觀察地址0x123456
info watchpoints 查看觀察點
delete num 根據編號num刪除觀察點
disable num 根據編號num禁用觀察點
enable num 根據編號num啟用觀察點

watchpoint使用方法

測試用例test_watchpoint.c

  1 /*================================================================
  2 *  Author: LiuHanxu
  3 *  Date: 2022-06-11
  4 *  Description: 
  5 ================================================================*/
  6 #include <stdio.h>
  7 
  8 int main()
  9 {
 10   int a = 1, b = 2, c = 3;
 11   printf("before: a = %d, b = %d, c = %d\n", a, b, c);
 12   int* ptr = &c;
 13   for(int i=0; i<=100; i++)
 14   {
 15     if (i == 66)
 16       a = 0;
 17     if (i == 88)
 18       b = 0;
 19     if (i == 99)
 20       *ptr = 123;
 21   }
 22   printf("after: a = %d, b = %d, c = %d\n", a, b, c);
 23   return 0;
 24 }

觀察變量watch a

給變量a設置觀察點,然后繼續運行,當a被修改后程序就停止運行,可以看出當循環變量i為66時,將a的值改為了0。因此,我們就很快定位到程序第16行改變了變量值,程序停到17行。

lhx@ubuntu:~/test_notes$ gdb ./test_watchpoint 
Reading symbols from ./test_watchpoint...
(gdb) b main
Breakpoint 1 at 0x1169: file test_watchpoint.c, line 9.
(gdb) r
Starting program: /home/lhx/test_notes/test_watchpoint 

Breakpoint 1, main () at test_watchpoint.c:9
9	{
(gdb) n
10	  int a = 1, b = 2, c = 3;
(gdb) n
11	  printf("before: a = %d, b = %d, c = %d\n", a, b, c);
(gdb) watch a
Hardware watchpoint 2: a
(gdb) c
Continuing.
before: a = 1, b = 2, c = 3

Hardware watchpoint 2: a

Old value = 1
New value = 0
main () at test_watchpoint.c:17
17	    if (i == 88) 
(gdb) i loc
i = 66
a = 0
b = 2
c = 3
ptr = 0x7fffffffe280

觀察表達式watch b+2*c

觀察表達式b+2*c,每次當表達式的值發生變化,程序就會暫停。通過下面調試結果發現在第18行時b的值改變導致表達式變化,第20行時c的值發生改變(此處是通過指針ptr修改c的值,所以gdb會定位到第12行,能發現循環變量i的值是99)。

lhx@ubuntu:~/test_notes$ gdb ./test_watchpoint 
Reading symbols from ./test_watchpoint...
(gdb) b main
Breakpoint 1 at 0x1169: file test_watchpoint.c, line 9.
(gdb) r
Starting program: /home/lhx/test_notes/test_watchpoint 

Breakpoint 1, main () at test_watchpoint.c:9
9	{
(gdb) n
10	  int a = 1, b = 2, c = 3;
(gdb) n
11	  printf("before: a = %d, b = %d, c = %d\n", a, b, c);
(gdb) n
before: a = 1, b = 2, c = 3
12	  int* ptr = &c;
(gdb) n
13	  for(int i=0; i<=100; i++)
(gdb) watch b+2*c
Hardware watchpoint 2: b+2*c
(gdb) c
Continuing.

Hardware watchpoint 2: b+2*c

Old value = 8
New value = 6
main () at test_watchpoint.c:19
19	    if (i == 99)
(gdb) c
Continuing.

Hardware watchpoint 2: b+2*c

Old value = 6
New value = 246
main () at test_watchpoint.c:13
13	  for(int i=0; i<=100; i++)
(gdb) i loc
i = 99
a = 0
b = 0
c = 123
ptr = 0x7fffffffe280
(gdb) c
Continuing.
after: a = 0, b = 0, c = 123
......

觀察地址watch *0x7fffffffe280

觀察變量c的地址,找出哪里修改變量c的值。通過命令watch *0x7fffffffe280觀察變量c的地址,定位到程序第12行修改了該地址,gdb顯示的下一行為13行,可以看到循環變量i為99。

lhx@ubuntu:~/test_notes$ gdb ./test_watchpoint 
Reading symbols from ./test_watchpoint...
(gdb) b 13
Breakpoint 1 at 0x11bd: file test_watchpoint.c, line 13.
(gdb) r
Starting program: /home/lhx/test_notes/test_watchpoint 
before: a = 1, b = 2, c = 3

Breakpoint 1, main () at test_watchpoint.c:13
13	  for(int i=0; i<=100; i++)
(gdb) i loc
i = 21845
a = 1
b = 2
c = 3
ptr = 0x7fffffffe280
(gdb) watch *0x7fffffffe280
Hardware watchpoint 2: *0x7fffffffe280
(gdb) c
Continuing.

Hardware watchpoint 2: *0x7fffffffe280

Old value = 3
New value = 123
main () at test_watchpoint.c:13
13	  for(int i=0; i<=100; i++)
(gdb) i loc
i = 99
a = 0
b = 0
c = 123
ptr = 0x7fffffffe280

調試截圖演示

image-20221223221138102


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM