gdb是C/C++程序员必备的专业技能,工作中gdb最常用的场景有两个,一个是分析core文件,另一个是调试程序。
分析core文件的方法如下:
1、gdb 程序名 core文件名
2、bt或where命令查看堆栈信息。
3、进入某个栈:f N,f是frame的缩写,N是栈号,如0、1、2、3...
进入到某个栈后,才能通过p命令查看这个栈的临时变量,否则只能查看全局变量。
例如a.out程序core产生了core文件core-a.out-12345,gdb方法如下:
gdb a.out core-a.out-12345
bt(或者where)
f 3,进入第3帧
调试一个正在运行的程序使用gdb -p PID命令,PID即程序的pid。
需要注意的是,gdb调试正在运行的程序会导致程序挂起,因此请记住不要gdb调试正在运行的在线服务。
设置断点的方式有很多种,最常见的有两种:一是设置程序运行到源代码的某一行,二是设置程序运行到某个函数。
设置程序运行到某一行,通过“文件名:行号”的形式:
b test.cpp:100
设置程序运行到某个函数,通过“名字空间::函数名”的形式:
gdb namespace_a::func
查看断点:info b
删除断点:d N,d是delete的缩写,N是断点的编号,可以通过info b查看。
无论哪种方式设置断点,都要执行c命令(continue),让程序继续运行。
在调试程序时,最常用的gdb命令是:n、s、p
n即next,单步执行,执行下一步的意思,遇到函数会调用函数。
s即step,也是单步执行,但是会进入函数内部,然后结合n命令来调试函数。
p即print,打印变量,最常用的命令。p可以打印普通变量、std::string字符串、指针、数组等。
gdb打印字符串支持c_str()、length()等:
std::string str;
p str,p str.c_str()查看字符串内容,p str.length(),查看字符串长度
有时会遇到字符串太长不能显示全,最后显示"...",可以通过命令取消长度限制:
set print elements 0
这样就能打印完整的字符串。
小提示:
1、gdb会自动保存上一次执行的命令,可以通过键盘的上下方向箭头切换最近输入的命令。
2、直接敲回车,会执行上一次的命令,在n单步调试的时候最常用。
面试中的gdb问题往往会很挑剔,除了考察常用的gdb命令,还会问一些多线程相关的命令,
例如怎么查看线程信息?怎么打印所有线程的当前栈信息?
gdb查看线程信息:info thread,可以查看线程编号和正在执行的函数
进入某个线程:t N,N是线程编号,如1、2、3...
查看所有线程的栈信息:thread apply all bt
这是面试官在考察面试者有没有多线程问题排查经验。
最后说一下gdb中如何打印STL的vector和map,gdb默认不支持STL,
需要从网上下载一个txt文件,然后将其内容追加到.gdbinit文件中,就可以使用pvector命令查看vector容器数据。