入门:C/C++中的段错误(Segmentation fault)【转】
GDB调试
|
|
一、暂停/恢复程序运行
1. 启动gdb
|
|
2. 设置断点
用break命令设置断点:
-
break <function> :在进入指定函数时停住
1 2break class::function break function(type, type) -
break <linenum> :在指定行号停住
-
break +offset / -offset : 在当前行的前 / 后的offset行停住
-
break filename:linenum :在源文件filename的linenum行停住
-
break filename::function :在源文件filename的function函数入口停住
-
break *address :在程序运行的内存地址处停住
-
break :没有加参数时,表示在下一条指令处停住
-
break … if <condition> :…可以是上述参数,condition表示条件,在条件成立时停住 (条件断点)
1break if i=100 #当i=100时,停住程序
查看断点,可使用 info 命令:
- info breakpoints [n] ( n 表示断点号)
- info break [n]
3. 设置观察点
watchpoint 一般用来观察某个表达式(变量也是一种表达式)的值是否有变化了,如果有变化,马上停住程序。我们有下面的几种方法来设置观察点:
- watch <expr> :为表达式(变量)expr 设置一个观察点。
- rwatch <expr> :当表达式(变量)expr 被读时,停住程序。
- awatch <expr> :当表达式(变量)的值被读或写时,停住程序
- info watchpoints :列出当前设置的所有观察点
4. 设置捕捉点
catchpoint 用来捕捉程序运行时的一些事件。如:载入共享库(动态链接库)或是 C++ 的异常。设置捕捉点的格式为:
-
catch <event> :当event发生时,停住程序
1 2catch throw #一个C++抛出的异常 catch catch #一个C++捕捉到的异常 -
tcatch <event> :只设置一次捕捉点,当程序停住后,点被自动删除
5. 维护断点
GDB 中的断点也就是上述的三类。在 GDB 中,如果你觉得已定义好的停止点没有用了,你可以使用 delete 、 clear 、 disable 、 enable 这几个命令来进行维护。
- clear :清除所有的已定义的停止点
- clear <function> 或 clear <filename:function> :清除所有设置在函数中的停止点
- clear <linenum> 或 clear <filename:linenum> :清除所有设置在指定行上的停止点
- delete [breakpoints] [range…] :删除指定的断点(breakpoints是断点号,若不指定断点号,表示删除所有的断点。range表示断点号的范围(如:3-7)。其简写命令为 d
- disable [breakpoints] [range…] :断点不会被删除,当再次需要时,enable即可。如果不指定断点,会disable所有断点
- enable [breakpoints] [range…]
- enable [breakpoints] once range… :使能指定的断点一次,当程序停住,该断点立刻被GDB禁用disable
- enable [breakpoints] delete range… :使能指定的断点一次,当程序停止后,该断点立刻被删除
6. 维护停止条件
一般来说,为断点设置一个条件,我们使用 if 关键词,后面跟其断点条件。并且,条件设置好后,我们可以用 condition 命令来修改断点的条件。 (只有 break 和 watch 命令支持 if, catch 目前暂不支持 if )
- conditon <bnum> <expression> :修改断点号为 bnum 的停止条件为 expression
- condition <bnum> :清除断点号 bnum 的停止条件
- ignore <bnum> <count> :指定程序运行时,忽略断点号为 bnum 的停止条件 count 次
7. 为断点设定运行命令
可以使用 GDB 提供的 command 命令来设置停止点的运行命令。 也就是说,当运行的程序在被停止住时,我们可以让其自动运行一些别的命令,这很有利行自动化调试。对基于 GDB 的自动化调试是一个强大的支持。
commands [bnum] … command-list … end
为断点号 bnum 写一个命令列表,当程序被该断点停住时,gdb 会依次运行命令列表中的命令。例如:
|
|
如果要清除断点上的命令序列,那么只要简单的执行一下 commands 命令,并直接在输个 end 就行了。
8. 断点菜单
在 C++ 中,可能会重复出现同一个名字的函数若干次(函数重载),在这种情况下, break <function> 不能告诉 GDB 要停在哪个函数的入口。
当然,你可以使用 break <function(type)> 也就是把函数的参数类型告诉 GDB,以指定一个函数。
否则的话,GDB 会给你列出一个断点菜单供你选择你所需要的断点。你只要输入你菜单列表中的编号就可以了。如:
|
|
可见,GDB 列出了所有 after 的重载函数,你可以选一下列表编号就行了。 0 表示放弃设置断点, 1 表示所有函数都设置断点。
9. 恢复程序运行和单步调试
当程序被停住了,可以用continue命令恢复程序的运行直到程序结束,或到下一个断点处。也可以使用step 或者 next 单步执行
- continue [ignore-count] 或者 c [ignore-count] 或者 fg [ignore-count] :恢复程序运行直到
Basic:
|
|
-
Output
1 2 3 4 5Temporary breakpoint 1 at 0x1169: file hello.c, line 3. Starting program: /home/jack/backup/opencvTest/a.out Temporary breakpoint 1, main () at hello.c:3 3 {
显示代码片段:
|
|
-
Output
1 2 3 4 5 6 7 8 9 101 #include<stdio.h> 2 int main(void) 3 { 4 int i = 0; 5 printf("Hello, world\n"); 6 printf("i is %d\n", i); 7 i++; 8 printf("i is now %d\n", i); 9 return 0; 10 }
无法显示中文
GDB
Ref:
-
(2024-01-19) 两个视频差不多又有区别,第一个画质好内容少一些,第二个画质差但内容多一些 冬眠贝尔熊 的评论
1. More than you knew
按下 Ctrl+x+a,从1979进入八十年代!类似图形界面的TUI,再按一遍回到命令行
-
ctrl + l : 刷新屏幕
-
ctrl + p / ctrl+n : prev / next command
-
ctrl + x + 2 : 第2个窗口,cycle though
-
或者输入:
tui enable,或者layout src,或者layout asm(显示汇编代码),进入 TUI
2. GDB has Python
-
Full Pyton interpreter with access to standard modules (unless your gdb installaion is messed up!)
-
The gdb python module gives most access to gdb
1 2 3(gdb) python gdb.execute() #执行gdb命令 (gdb) python gdb.parse_and_eval() #to get data from inferior (gdb) python help('gdb') #to see online help -
Python Pretty Printers
1 2 3 4 5class MyPrinter(object) def __init__(self,val): self.val = val; def to_string(self): return (self.val['member'])1 2 3 4import gdb.printing pp = gdb.printing.RegexpCollectionPrettyPrinter('mystruct') pp.add_printer('mystruct', '^mystruct$', MyPrinter) gdb.printing.register_pretty_printer( gdb.current_objfile(),pp)
3. In-built pretty printers for STL
GDB will ( try to ) pretty-print most STL container classes ( std : : vector , std : string , etc ) , e.g.
|
|
Note that this relies on Python pretty printers installed on the target system
Compiling / linking with a different version of libstdc + + ( e . g . executable built on a different host than the one beingused to debug ) , then pretty printing might give strange results.
There are many ( list with info pretty-printers ) , includingstd : string , std : bitset , std : list , std : multimap , std : queue , std : set , std : shared _ ptr ,std : stack , std : tuple , std : unique _ ptr , std : vector , std : weak _ ptr , and iterators.
4. .gdbinit
5. GDB is built on ptrace and signals
GDB是建立在ptrace之上的。当一个正在被跟踪的程序收到一个信号,它会暂停并且tracer会通过waitpid 注意到,所以当 the inferior收到信号,它就会停止然后gbd获得控制。通常gdb会回到prompt,但是具体会做什么取决于信号和设置。
|
|
有两个信号很特别:
- SIGINT 当在按下 Crtl+c 会产生
- SIGTRAP 当 the inferior 遇到断点或者单步调试时会产生。(改变代码,0xCC操作码生成陷阱)
|
|
6. Breakpoints & watchpionts
|
|
foo 是一个局部变量
7. thread apply
|
|
8. Dynamic Printf
不需改变代码,用printf的话需要考虑加在哪里,然后重新编译运行,查看输出,没查到结果,又要重复一遍
9. Calling inferior functions
call foo will call foo in your inferior
10. Catchpoints
像断点
11. Remote debugging
通过serial/sockets 调试远程服务器。
gdbserver localhost:2000 ./a.out
12. Multiprocess Debugging
Modern
Source video: 【GDB调试教程】如何设置条件断点?如何动态修改变量?Python和C++混合怎么调试?如何附加到进程?- 双笙子佯谬 - bilibili
(2024-01-19)
-
调试 Python 程序
用 gdb 调试 python,进入之后把要调试的 test.py 文件作为参数传入. vid
1 2 3 4 5 6 7gdb test.py # This trivial way won't work. gdb python # debug python r test.py # i.e., shell cmd: `python test.py` # the appended arguments will be put into argv # Or, with `-ex` gdb python -ex 'r test.py'这样,GDB 就可以捕获 python 的异常。
TODO: Debugging Python C extensions with GDB - Redhat Developers
-
Temporary breakpoint only break once.
1tb func