GDB (全称为GNU Debuger) 是一款由 GNU 开源组织发布、基于 UNIX/LINUX 操作系统的命令行程序调试工具。对于一名 Linux 下工作的 C++ 程序员,GDB 是必不可少的工具。
GDB常用调试命令
为了便于讲解,将通过以下 demo 进行举例说明。
1 2 3 4 5 6 7 8 9 10 11 12 13
#include<iostream> usingnamespace std; intadd(int a,int b){ int sum = 0; sum = a + b; return sum; } intmain(int argc,char *argv[]){ int sum = 0; sum = add(1, 2); cout << sum << endl; return0; }
(base) sv@sv-NF5280M5:/home/sv/桌面$ gdb main GNU gdb (Ubuntu 9.2-0ubuntu1~20.04.1) 9.2 Copyright (C) 2020 Free Software Foundation, Inc. License GPLv3+: GNU GPL version 3 or later <http://gnu.org/licenses/gpl.html> This is free software: you are free to change and redistribute it. There is NO WARRANTY, to the extent permitted by law. Type "show copying" and "show warranty"for details. This GDB was configured as "x86_64-linux-gnu". Type "show configuration"for configuration details. For bug reporting instructions, please see: <http://www.gnu.org/software/gdb/bugs/>. Find the GDB manual and other documentation resources online at: <http://www.gnu.org/software/gdb/documentation/>.
For help, type"help". Type "apropos word" to search for commands related to "word"... Reading symbols from main... (gdb)
2. 终端列出源代码
我们可以在终端列出要调试的代码,这样可以不用打开源文件查看。
1
list // 执行一次列出 10 行代码,再执行一次列出后面 10 行代码
效果如图 2 所示:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18
For help, type"help". Type "apropos word" to search for commands related to "word"... Reading symbols from main... (gdb) list 1 #include <iostream> 2 using namespace std; 3 int add(int a,int b){ 4 int sum = 0; 5 sum = a + b; 6 returnsum; 7 } 8 int main(int argc,char *argv[]){ 9 int sum = 0; 10 sum = add(1, 2); (gdb) 11 cout << sum << endl; 12 return 0; 13 }
3. 设置断点
断点是程序调试的关键所在,随心所欲地设置断点使我们调试程序变得高效。
断点打在源程序第 n 行:
1
break n // 在源程序第 n 行设置一个断点,break 可以用 b 缩写替代
断点打在源程序 main() 函数入口:
1
break main // 在 main() 函数入口打断点,也就是第 9 行,break 可以用 b 缩写替代
上面是打在源文件的函数入口,若要将断点打在其他文件的函数入口或者其他文件的特定行号应该怎么做呢?
下面的命令可以解决:
1 2 3
break otherfile:func // 断点打在其他文件的函数入口 break otherfile:n // 断点打在其他文件的第 n 行 // 注:otherfile 为其他文件,例如 sort.cpp,而 n 代表行号
(gdb) b main Breakpoint 1 at 0x11ce: file main.cpp, line 8. (gdb) b 10 Breakpoint 2 at 0x11e8: file main.cpp, line 10. (gdb) info b Num Type Disp Enb Address What 1 breakpoint keep y 0x00000000000011ce in main(int, char**) at main.cpp:8 2 breakpoint keep y 0x00000000000011e8 in main(int, char**) at main.cpp:10 (gdb) delete Delete all breakpoints? (y or n) y (gdb) info b No breakpoints or watchpoints.
4. 运行程序
运行程序命令与我们 IDE 调试程序类似,两者可以作对比。
1 2 3 4 5 6 7 8
run // 类比于 IDE 的全速运行,遇到断点会停下,run 可以用 r 缩写替代 next // 类比于 IDE 不进入函数的单步调试,next 可以用 n 缩写替代 step // 类比于 IDE 进入函数的单步调试,step 可以用 s 缩写替代 continue// 继续执行直到遇到下一个断点停下,没有断点直接结束,可以用 c 缩写替代 until n // 直接跳转到指定行号程序,n 表示行号 finish // 当程序运行在函数中时,直接执行完当前函数并打印函数返回信息 kill // 直接结束当前进程,程序可以从头运行 quit // 退出 GDB,quit 可以用 q 缩写替代
5.打印信息
1 2
print x // 可以打印变量、地址、表达式值等,x 表示需要打印的东西,print 可以用 p 替代 bt // 打印当前调用堆栈的信息,后面会继续讲