做linux有将近一年的时间了,说我都没用过gdb,有人相信吗?
不过这是真的,之前只有自己练习的时候使用,实际工作中没用过,可能是自己没有遇到特别困难的问题,一般都是printf搞定了,不过,我越来越觉得gdb的必要性,从今天开始学习使用gdb,在此不断的记录学习心得。
- 如果使用gdb,在编译的时候一定加上-g
- 启动gdb
- gdb a.out
- gdb attach pid
- gdb -> at pid
- 设置断点方法
- break 进入函数停住,C++采用class::function
- break 指定行号停住
- break +offset/ break -offset 在当前行号的前面或后面offset行停住
- break filename:linenum 在源文件filename的linenum行停住
- break *address,在运行的内存地址出停住
- break 没有参数时,表示在下一条指令出停住
- break if 表示条件成立时停止
- 删除断点
- info breakpoint 列出断点列表
- delete number 删除断点
- delete n:m 删除n到m所有断点
- 单步命令
- next (简写为n) 类似于step over, 不会进入函数内部
- step (简写为s) 进入函数内部
- next 执行count步后停住,不进入调用函数内部
- step 执行count步后停住,进入调用函数内部,此函数编译有debug信息
- set step-mode 打开stop-mod模式,这样进入单步跟踪(step命令)时,若跨越没有调试信息的函数,则程序则会在该函数的第一条指令处停止,而不会跳过整个函数
- finish 运行程序,直到当前函数完成返回,并打印函数返回时的堆栈指针,返回值及参数值等信息
- until (u) 退出循环
- stepi (si) 和 nexti (ni) 单步跟踪一条机器指令
- continue (c) 当程序被停止后,可以使用continue恢复程序直到程序结束或者到达下一个断点
- c [ignore-count]
- continue [ignore-count]
- fg [ignore-count]
- print 命令
- p 打印变量值
- p / f为格式, x:16进制, d:10, u:16无符号,o:8, t:2, a:16, c:字符,f:浮点
- @操作符,int array = (int)malloc(len*sizeof(int)); p *array@len, 可以显示len长度个数据
- print x=4 改变变量的值
- 1, 2…. 过往print的结果,可以直接引用
- watch
- watch 为表达式(变量)expr设置一个观察点,一旦表达式值由变化,马上停止运行
- rwatch 当表达式(变量) expr被读时,停止程序运行。
- awatch 当表达式(变量) expr的值被读或被写时,停止程序运行
- info watchpoints 列出当前设置的所有观察点
- examine (x) 查看内存
- x / [n/f/u] x/后面的n,f,u都是可选的参数, n表示显示内存的长度,f表示显示格式, 字符串为s,地址为i,u表示从当前地址往后请求的字节数,如果不指定,默认是4字节, b:单字节, h:双字节,w:四字节,g:八字节, 如 x/3uh 0x54320
- set 修改内存
- (gdb)set (unsigned char )p = ‘h’
- (gdb)set (unsigned char )(p+1) = ‘e’
- (gdb)set (unsigned char)(0x602010)=’l’
- jump 命令, 提供乱序执行代码功能
- jump [linespec] 后面跟行号,可以是file:line格式
- jump +num 偏移格式
- jump [address] 后面跟内存地址
- jump命令用在一个函数内部,跨函数出栈时会有问题
- signal 命令
- signal [signal] 1-15,产生SIGINT信号
- return 忽略断点后还没有执行的函数代码
- call命令 强制执行调用函数
- call strcpy(p,”hello world”);
- call printf(%s\n”,p)
- info命令
- info registers 查看除了浮点寄存器以外的寄存器
- info all-registers 查看所有寄存器 包括浮点寄存器
- info registers [regname …] 查看指定的寄存器
- info break 查看断点信息
- info watchpoints 查看所有观察点
- info signals 查看gdb正在检测的信号
- info handle 同info signals
- info line 查看源代码在内存中的地址, 后面可跟行号,函数名,文件名:行号,文件名:函数名等多种形式, 如 info line main.c:main
- disassemble 用于反汇编,查看当前执行时源代码的机器码,实际上只是把目前内存中的指令冲刷出来
- disassemble func