gdb是GNU开源组织发布的一款Linux系统下的程序调试工具。相比windows系统,虽然gdb调试工具没有windows系统下可视化调试页面(如windows的VC、VS等IDE调试页面),但gdb调试工具也具有windows调试工具几乎全部的调试功能,而且gdb调试工具还具有修复网络断点和恢复链接等功能。
gdb工具的调试功能主要有下面四点:
(1)启动调试程序,可以按照用户自定义的要求启动运行程序。
(2)使调试程序在指定断点处停止。(断点可以是设置的普通断点、条件表达式)
(3)当程序被停住时,可以检查此时程序的停止之前的运行过程。
(4)可以改变你的程序,将一个bug产生的影响修正从而测试其他的bug。
关于gdb的介绍可以参考gdb_百度百科 (baidu.com)
g++ -g main.cpp -o main //生成带有调试信息的可运行程序main,编译参数-g
linux下g++生成可运行程序的用法总结可参考linux下g++编译C++工程demo与g++命令简述_夜雨听萧瑟的博客-CSDN博客_g++编译命令linux
测试程序demo如下:
#include
#include
using namespace std;
int main()
{
cout <<"hellword" << endl;
return 0;
}
生成可执行文件命令如下:
g++ testNoArg.cpp -o mainNoArgNoDebug //生成可执行文件不带调试信息
g++ -g testNoArg.cpp -o MainNoArgDebug //生成可执行文件带有调试信息
结果如下:
方法1:
a> 输入gdb。
b>输入file mainNoArgNoDebug
没有调试信息的结果如下:
有调试信息的结果如下:
可以看出,没有调试信息的会提示:No debugging symbols found in....,有调试信息的会提示Reading symbols from ....。
方法2:
使用readelf命令来显示elf格式的目标文件格式。(elf文件有三种类型:a>可重定位文件:用户和其他目标一起创建可执行文件或者共享目标文件,如lib*.a文件。b>可执行文件:生成进程映像,载入内存运行,如可执行文件*.out。c> 共享目标文件:用于和其他共享目标文件或者可重定位文件一起生成可执行文件,如*.so。)
readelf的选项参数有-a,-h,-l,-S,-g,-t,-s,-e,-n,等,此处使用参数-S,查看elf文件的节头信息,节头是对可执行程序中代码段和数据位置和大小的描述。
没有调试信息结果如下:
有调试信息的结果如下:
关于readelf命令用法可参考readelf命令_Linux readelf 命令用法详解:用于显示elf格式文件的信息 (ailinux.net)
关于elf文件节头格式描述如下:ELF文件格式第三讲,节头(section header) (icode9.com)
关于elf文件格式内容参考:ELF(文件格式)_百度百科 (baidu.com)
ELF文件格式的详解_pingxiaozhao的博客-CSDN博客_elf 文件格式
******gdb调试目标程序方式(默认以不带参可执行程序为例,程序为(1)中code)start*****
在gdb中调试程序方式种类:
//第一种:直接启动。命令:gdb filenName (程序未运行,运行起来后需要run)
gdb ./MainNoArgDebug //直接加载带有调试信息的可执行文件
//第二种:附加进程,命令:gdb attach pid (程序已运行)
./testMain //(1)运行可执行程序
ps aux | grep testMain //(2)查看进程ID
gdb attach ID //(3)关联程序id,进入调试.注意需要root账户
//第三种:调试coredump文件,命令:gdb filename corename
查看linux是否开启了产生dump文件的信息,命令:ulimit -a
上面的第一种:调试未启动的程序方法,还有另一种:先加载gdb,再将待调试程序加载进来。
优点:可以file多次指定不同文件,重新启动不同的可执行文件
gdb //(1)加载gdb
file MainNoArgDebug //(2)加载带有调试信息可运行文件
注:上面第二种和第三种调试程序的方式会在其他博客介绍。本文主要以第一种为主。
关于这三种的有关介绍也可参考:gdb 笔记(02)— gdb 调试执行(启动调试、添加参数、附加到进程、调试 core 文件)-pudn.com
******gdb调试目标程序方式(默认以不带参可执行程序为例,程序为(1)中code)end*****
run命令运行调试程序:运行程序,直到运行程序结束,或遇到断点停止(简写命令r)。运行如下:
start命令:启动可执行程序,运行到main函数的第一句出停止,如下:
************************************gdb带参程序方法start************************************
demo的代码如下:
1 #include
2 #include
3 using namespace std;
4 int main(int argc,char** argv)
5 {
6 std::cout << "argc value is " << argc << std::endl;
7 for(int i = 0; i < argc; i++)
8 {
9 std::cout << "i is " << i << " Value is " << argv[i] << std::endl;
10 }
11
12 return 0;
13 }
demo 代码简单回顾:
argc参数:统计参数格式,其中记录了命令行中命令和参数的个数;
argv:指向字符指针的指针,实质时数组。里面存的数据顺序是:命令,参数1,参数2,,,
关于main函数详细可参考main函数_百度百科 (baidu.com)
//非gdb下带参程序运行
a>生成可执行文件testArgDebug,命令: g++ -g testArgDebug.cpp -o testArgDebug
b>输入带参并运行代码,命令: ./testArgDebug 12 34
结果如下:
//gdb下带参程序运行
gdb下带参程序的运行有以下两种方式:
a> 先设置参数,再利用run运行程序。命令:set args
该命令需要注意:如果没有设置参数,则与前一个命令使用的参数相同,该命令详细介绍可参考:
参数(使用 GDB 调试) (sourceware.org)
该方法启动程序的过程如下:
b> 在run时添加参数,启动调试程序过程如下:
上面的两种方式都可以
************************************gdb带参程序方法end*************************************
gdb中显示源码的命令为list,需要注意的是可执行文件需要跟源码在同级目录。
测试的demo如下:
1 #include
2 #include
3 using namespace std;
4 void ConvertFunc(int &a,int &b)
5 {
6 a = a+b;
7 b = a - b;
8 a = a-b;
9 }
10
11 int FindMaxVal(int a[],int nNum)
12 {
13 int temp = 0;
14 for(int i = 0;i < nNum;i++)
15 {
16 if(a[i] > temp)
17 {
18 temp = a[i];
19 }
20
21 }
22 return temp;
23 }
24
25 int FindMinVal(int a[],int nNum)
26 {
27 int temp = 100000;
28 for(int i = 0;i < nNum;i++)
29 {
30 if(a[i] < temp)
31 {
32 temp = a[i];
33 }
34
35 }
36 return temp;
37 }
38
39 int main()
40 {
41 int nA = 10;
42 int nB = 20;
43 cout << "Before Switch nA is " << nA << " nB is " << nB << endl;
44 ConvertFunc(nA,nB);
45 cout << "After Switch nA is " << nA << " nB is " << nB << endl;
46
47 int arrnVal[] = {3,2,90,26,50};
48 int nMaxVal = 0;
49 nMaxVal = FindMaxVal(arrnVal,sizeof(arrnVal)/sizeof(arrnVal[0]));
50 int nMinVal = 0;
51 nMinVal = FindMinVal(arrnVal,sizeof(arrnVal)/sizeof(arrnVal[0]));
52 cout << "Arr Max val is " << nMaxVal << " Min val is " << nMinVal << endl;
53 return 0;
54 }
55
list相关命令如下(简写命令l):
a>list num:显示已num行为中心,前后共10行代码显示在屏幕上。
eg:
b>list 将当前显示行及后面的代码显示在屏幕上,默认显示10行。
eg:
c>list -:显示当前行前面的代码。
d>list function:显示名为function函数的源程序。
eg:
在查看代码过程中,按下Enter按键会自动往下切换显示代码,如下:
因为在gdb中,执行完一个命令后,不输入任何命令,直接回车,gdb会默认执行上一个命令。
show命令是描述gdb本身相关状态信息,通过在show后面+具体的参数可以获取对应信息。
a>show args 显示程序启动时的参数。
eg:
b>show environment 打印程序运行时的环境变量
eg:
show的参数还有更多,如 language、paths、code-cache等,可以自行查看。
使用测试的demo为(3)中的代码。
注:在启动时可以设置不显示gdb相关版本信息,命令为 gdb -q a.out
***设置断点break(简写b)
a>break function(type,type) /break class::function在函数function处设置断点.
b>break lineNum 在代码指定的行数设置断点
eg
c>break line-or-function if exp设置条件断点,在行数line处或者在function处设置具体条件
eg:
注意条件变量的设置必须时该变量生命周期内,否则条件变量不会生效!
***查看断点 info break(简写info b)
eg:如上面c>中的图。
设置自动显示变量:display
继续运行到下一个断点命令:continue
***删除断点: delete breakpoints Num
eg:
关于断点设置的其他命令不再演示。
gdb的官网信息见:Top (Debugging with GDB) (sourceware.org)
gdb文档下载地址:Documentation for GDB version 12.1 (sourceware.org)
下载Top(Debugging withGDB)下的gdb.pdf
gdb的环境下载: Download GDB (sourceware.org)
后续更新中...