Linux下gdb调试方法介绍

1、gdb介绍

        gdb是GNU开源组织发布的一款Linux系统下的程序调试工具。相比windows系统,虽然gdb调试工具没有windows系统下可视化调试页面(如windows的VC、VS等IDE调试页面),但gdb调试工具也具有windows调试工具几乎全部的调试功能,而且gdb调试工具还具有修复网络断点和恢复链接等功能。

        gdb工具的调试功能主要有下面四点:

        (1)启动调试程序,可以按照用户自定义的要求启动运行程序。

        (2)使调试程序在指定断点处停止。(断点可以是设置的普通断点、条件表达式)

        (3)当程序被停住时,可以检查此时程序的停止之前的运行过程。

        (4)可以改变你的程序,将一个bug产生的影响修正从而测试其他的bug。

关于gdb的介绍可以参考gdb_百度百科 (baidu.com)

2、gdb用法介绍

(1)生成带有调试信息的可运行程序,命令如下:

g++ -g main.cpp -o main    //生成带有调试信息的可运行程序main,编译参数-g

 linux下g++生成可运行程序的用法总结可参考linux下g++编译C++工程demo与g++命令简述_夜雨听萧瑟的博客-CSDN博客_g++编译命令linux

判断可运行程序是否带有调试信息?

测试程序demo如下:

#include <iostream>
#include <string>
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 文件格式

(2)运行调试程序:(gdb)run、start

******gdb调试目标程序方式(默认以不带参可执行程序为例,程序为(1)中codestart*****

在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*****

 上面的第一种方式gdb filenName命令执行后程序是未运行的,需要使用run或start命令进行运行,它们的介绍如下:

run命令运行调试程序:运行程序,直到运行程序结束,或遇到断点停止(简写命令r)。运行如下:

 start命令:启动可执行程序,运行到main函数的第一句出停止,如下:

 附加知识:启动带参可执行程序

************************************gdb带参程序方法start************************************

demo的代码如下:


     1	#include <iostream>
     2	#include <string.h>
     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*************************************

(3)源码查看:(gdb)list

gdb中显示源码的命令为list,需要注意的是可执行文件需要跟源码在同级目录。

测试的demo如下:

     1	#include <iostream>
     2	#include <string.h>
     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会默认执行上一个命令。

(4)运行参数查看show

show命令是描述gdb本身相关状态信息,通过在show后面+具体的参数可以获取对应信息。

a>show args 显示程序启动时的参数。

eg:

 b>show environment  打印程序运行时的环境变量

eg:

 show的参数还有更多,如  language、paths、code-cache等,可以自行查看。

(5)断点设置

设置断点、设置条件断点、查看断点、删除断点、禁用断点、运行某个断点:(gdb)break、break...if conditon、info b、delete break 1、disable break 1、enable break

使用测试的demo为(3)中的代码。

注:在启动时可以设置不显示gdb相关版本信息,命令为 gdb -q  a.out

***设置断点break(简写b)

        a>break function(type,type) /break class::function在函数function处设置断点.

     eg:

         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:   

关于断点设置的其他命令不再演示。

(6)单步运行、继续运行:(gdb)next、continue

(7)进入函数:(gdb)step

(8)变量查看(变量实时显示):(gdb)watch、display

(9)窗口分割:(gdb)layout

(10)变量检测、赋值:(gdb)whatis、ptype、set variable=val

(11)查看函数调用堆栈:(gdb)backtrace、

(12)信号用法:(gdb)Handle

(13)终止调试:(gdb)quit

附加知识

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)

后续更新中...

猜你喜欢

转载自blog.csdn.net/hanxiaoyong_/article/details/126548015