gdb 内存断点watch 的使用
https://blog.youkuaiyun.com/hejinjing_tom_com/article/details/50570442
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
GDB常用命令总结
http://blog.sina.com.cn/s/blog_7880d3350102vw2d.html
在低端微控制器上进行仿真时,直接使用JTAG和IDE集成开发环境进行在线调试,不仅操作简单,而且界面良好,运行情况和结果非常直观。但是在Linux平台,很少有类似的集成开发环境,Linux上的GDB使用命令操作的方式,而且它要比集成开发环境强大多。下面是整理的常用的GDB调试命令。
编译时必须添加-g才能利用GDB进行调试,如:gcc -g test.c -o test
1. gdb -tui test打开调试程序,界面分页,上面是代码,下面是命令;
2. gdbtui的开关快捷键:ctrl+x ctrl+a或者ctrl+x A
3. file test在运行gdb下打开某个文件
4. run/r 运行
5. continue/c 继续运行
6. step/s 如果有函数则进入函数执行
7. finish 跳出当前的函数
8. stop 停止运行
9. until xxx 可用于跳出循环
10. guit/ctrl+d 退出GDB
11. print/p var 打印变量的值
12. print/p &var 打印变量地址
13. printf/p *addr 打印地址的值
14. printf/p /x var 用16进制显示数据
x十六进制/d十进制/u十六进制无符号/t二进制/c字符/f浮点
15. break/b xxx 在某行打断点
16. break/b fun 在某个函数处加断点
17. break/b 30 if n==100 //当变量n等于100的时候在30行处加断点
18. break fileName:N 在某个文件的N行加断点
19. info break/b 查看断点
20. clear N 删除N行断点
21. delete N 删除N号断点
22. delete 删除所有断点
23. disable xxx 失能断点
24. enable xxx 使能断点
25. info b 查看断点
26. info source 查看当前程序
27. info stack 查看堆栈信息
28. info args 查看当前参数值
29. display args 查看当前参数值
30. bt 查看函数堆栈
31. pwd查看程序路径
32. ctrl+p 前一条命令
33. ctrl+n 下一条命令
34. watch xxx 设置监控点,在变量改变的时候停下来。(不可直接设置,先加断点在监测)
35. ctrl+l可能layout会造成控制台花屏,使用ctrl+L清屏
36. list linenum:以linenum指定的行号为中心,显示10行
37. list function:以指定的函数为中心,显示10行
38. list:重复上一次的list指令,也可以直接按回车键,重复上次指令。
39. set listsize count:设置每次显示的行数。
40. show listsize:显示已设置的显示行数。
41. list first,last:显示指定起始行到结束结束行的源文件。
42. list ,last:显示以指定的last为结束行,显示10行。
43. list first,:以first为第一行,显示10行。
44. list +:以上次显示的结束行为起始行显示后10行
45. list –:以上次显示的起始行为结束行,显示前10行
gdb 调试时指定跳到第几行
https://www.cnblogs.com/habibah-chang/p/5160246.html
假设要从当前位置(main.c, ln 18)跳到 main.c, ln 21,忽略中间的 main.c, ln 19 ~ ln 20,可以这样做:(jump 缩写是 j)
(gdb) b 21
(gdb) j 21
在 (gdb) c 之后,gdb 会跳过 ln 19 ~ ln 20,停在 ln 21
注意:
1)要在 ln 21 设置断点,否则 gdb 会在 jump 到 ln 21 之后继续执行,直到下一个断点或程序结束
2)如果要忽略的是一个函数调用,比如像下面这样,运行到 ln 10,要跳到 ln 12
10 i++;
11 i = foo();
12 i--;
可以:
(gdb) step
(gdb) return
即,进入 foo(),然后直接返回。但是,要小心 foo() 的返回值。如果这样做不方便的话,采用上面的方法,即
(gdb) b12
(gdb) j 12
也可以