Linux下gdb调试工具的使用

gdb是GNU开源组织发布的一个强大的Linux下的程序调试工具。

gdb主要完成四个方面的功能:(1)、启动你的程序,可以按照你的自定义的要求随心所欲的运行程序;(2)、可让被调试的程序在你所指定的调试的断点处停住(断点可以是条件表达式);(3)、当程序被停住时,可以检查此时你的程序中所发生的事;(4)、动态的改变你程序的执行环境。

要想运行准备调试的程序,可使用run命令,在它后面可以跟随发给该程序的任何参数,包括标准输入和标准输出说明符(<;和>;)和shell通配符(*、?、[、])在内。如果你使用不带参数的run命令,gdb就再次使用你给予前一条run命令的参数。利用set  args命令就可以修改发送给程序的参数,而使用show  args命令就可以查看其缺省参数的列表。

一般来说,gdb主要调试的是c/c++的程序,也可以调试Ada、Objective-C、Pascal及其它语言。要调试c/c++的程序,首先在编译时,我们必须要把调试信息加到可执行文件中。使用编译器(cc/gcc/g++)的-g(-ggdb)参数可以做到这一点。如果没有-g,你将看不见程序的函数名、变量名,所代替的全是运行时的内存地址。

启动gdb的方法:(1)、gdb  <program> :program就是执行文件,一般在当前目录下;(2)、gdb  <program>  core:用gdb同时调试一个运行程序和core文件,core是程序非法执行后core  dump后产生的文件;(3)、gdb  <program>  <PID> :如果是一个服务程序,你可以指定这个服务程序运行时的进程ID。gdb会自动attach上去,并调试它。

gdb中,输入命令时,可以不用打全命令,只用打命令的前几个字符就可以了,当然,命令的前几个字符应该要标志着一个唯一的命令,在Linux下,可以敲击两次Tab键来补齐命令的全称,如果有重复的,那么gdb会把相关的全例出来。

gdb调试中常用的命令:

(1)、l或list命令,查看源码;

(2)、r或run命令,运行程序,会在有断点的地方停住,如果是有输入参数的,则为run  argv[1]  argv[2];

(3)、break  n,在源程序第n行处设置断点;break  fun,在函数fun()入口处设置断点;break  filename:function ,在源文件filename的function函数的入口处设置断点;breakfilename:linenum ,在源文件filename的第linenum行处设置断点;break  if<condition>, 在条件成立时停住;filename可以是相对路径,即你不仅可以在当前原文件中设置断点,也可以在该程序中用到的其它目录中的原文件中设置断点;

(4)、info命令,查看指定命令信息,如info  break会显示所有设置的断点信息;

(5)、n或next命令,单条语句执行,如果有函数调用,它不会进入该函数;

(6)、c或continue命令,继续运行程序;

(7)、p或print 变量名var,打印变量var的值。print是gdb的一个功能很强的命令,利用它可以显示被调试的语言中任何有效的表达式。表达式除了包含你程序中的变量外,还可以包含以下内容:A、对程序中函数的调用;B、数据结构和其它复杂对象;

(8)、bt或backtrace命令,查看函数调用栈的所有信息,当程序执行异常时,可通过此命令查看程序的调用过程;

(9)、finish命令,运行程序,直到当前函数完成返回;

(10)、q或quit命令,退出gdb;

(11)、set命令,可指定运行时变量名的值;

(12)、watch  <expr>,为表达式(变量)expr设置一个观察点,一旦表达式的值有变化时,马上停住程序;rwatch <expr>,当表达式(变量)expr被读时,停住程序;awatch  <expr>,当表达式(变量)的值被读或被写时,停住程序;

(13)、clear命令,清除所有的已定义的停止点,如断点等;clear <filename:function>,清除所有设置在函数上的停止点;clear <filename:linenum>,清除所有设置在指定行上的停止点;

(14)、step命令,单步跟踪,如果有函数调用,它会进入该函数,如果想退出该函数返回到它的调用函数中,可以使用finish命令;

(15)、jump命令,可以修改程序的执行顺序,可以让程序执行随意跳跃;

(16)、whatis命令,可以显示某个变量的类型;

要想了解gdb的更详细的用法,可以从http://www.gnu.org/software/gdb/documentation/下载gdb  manuals。

以下以一个测试程序为例,说明其中的一些命令的具体用法,此例程的组织结构为:gdbtest为总目录,下面有include/demo/src三个目录,(1)、include/add/add.h, include/subtract/subtract.h;(2)、src/add/add.cpp,src/subtract/subtract.cpp;(3)、demo/test/test.cpp。

每个文件的详细内容为:

add.h:

#ifndef _ADD_H_
#define _ADD_H_

int CalAdd(int a, int b);
float CalAdd(float a, float  b, float c);

#endif //_ADD_H_

subtract.h:

#ifndef _SUBTRACT_H_
#define _SUBTRACT_H_

int CalSubtract(int a, int b);
float CalSubtract(float a, float b);

#endif //_SUBTRACT_H_

add.cpp:

#include "../../include/add/add.h"

int CalAdd(int a, int b)
{
	int tmp1 = a / 2;

	if (b % 2 == 1) {
		b = b * 2 + 3;
	} else {
		b = b + 5;
	}

	int tmp2 = -1;

	tmp1 = a + tmp1 + b + tmp2;

	return tmp1;
}

float CalAdd(float a, float b, float c)
{
	float tmp1 = a - b;

	for (int i = 0; i < 10; i ++) {
		float tmp2 = i * 0.5;

		tmp1 += tmp2;
	}

	float tmp2 = a + c - b - tmp1;

	return tmp2;
}

subtract.cpp:

#include "../../include/subtract/subtract.h"

int CalSubtract(int a, int b)
{
	int tmp1 = 5;

	while (tmp1) {
		int tmp2 = 100;

		a += tmp2 / 2;

		-- tmp1;
	}

	int  tmp3 = a - b;

	return tmp3;
}

float CalSubtract(float a, float b)
{
	float tmp1 = -111;

	for (int i = 0; i < 100; i ++) {
		float tmp2 = -199;

		a -= b;

		a += tmp2;
	}

	float tmp3 = a - b;

	return tmp3;
}

test.cpp:

#include <iostream>
#include <stdlib.h>
#include "../../include/add/add.h"
#include "../../include/subtract/subtract.h"

using namespace std;

int main(int argc, char* argv[])
{
	cout<<"integer test, input integer:"<<endl;

	int a = 5, b = 10;

	if (argc > 1)
	  a = atoi(argv[1]);

	if (argc > 2)
	  b = atoi(argv[2]);

	int ret = 0;

	cout<<"start add:"<<endl;
	ret = CalAdd(a, b);
	cout<<"integer add :"<<ret<<endl;

	cout<<"start subtract:"<<endl;
	ret = CalSubtract(b, a);
	cout<<"integer subtract:"<<ret<<endl;

	cout<<"ok!!"<<endl;

	return 0;
}

打开终端,定位为到/demo/test/目录下,依次输入:

g++  -c  -g  test.cpp  ../../src/add/add.cpp  ../../src/subtract/subtract.cpp
g++  -o  test  test.o  add.o  subtract.o

会在test目录下生成test.o, add.o, subtract.o和test执行文件。

下面开始调试test:

(1)、输入gdb test,会显示:

(2)、先用l或list命令,查看当前原文件源码,每次会显示10行,每次显示行数也可以设置,如果想继续查看后面的代码,可以直接按Enter键,表示继续执行上次输入的命令:

(3)、为了不让程序一次性执行完,可以先设置一个断点,后面根据需要可以随时再增加断点,输入break  22,在当前文件test.cpp的第22行设置断点,输入info break查看此断点信息:

(4)、使用run命令开始正式调试test,输入run 10  20:

(5)、使用n或next命令,单步调试,接着输入step命令进入到CalAdd函数内部:

(6)、多设置几个断点:break  ../../src/add/add.cpp:13,break ../../subtract/subtract.cpp:5, break 26, 输入info break查看:

(7)、输入finish命令,从CalAdd函数内部退出,使用whatis命令,查看变量ret类型,输入print ret查看变量值:

(8)、使用continue命令,执行到下一个断点设置处:

(9)、使用clear命令,清除指定的断点:

(10)、如果想从头再次重新调试程序,可接着输入run 30  40,之前设的断点继续有效,如退出gdb调试,直接输入q或quit即可:

参考文献:

1.      http://www.gnu.org/software/gdb/

2.      http://blog.csdn.net/haoel/article/category/9197

时间: 2024-10-14 00:03:57

Linux下gdb调试工具的使用的相关文章

Linux知识(5)----LINUX下GDB调试

参考资料: 1.LINUX下GDB调试

Linux 下GDB的使用之简单入门

Linux 下程序崩溃.先要生成Core文件方可调试(这里Test为被调试程序) 1.查看Core文件(相当于Windows下的dump)大小,如果为0,则不会生成core文件 ulimit -c 查看core文件大小 ulimit -c filesize 设置大小为filesize ulimit -c unlimited 设置core大小为无限制 2.启动被调试程序 进入到被调试程序目录,输入gdb ./Test  回车 如果被调试程序有参数需设置,则 set args xxxx 回车 3.设

Linux下gdb调试

关于gdb的其他客套话不多说,直接进入正题. 一.gdb基本命令列表: 命令 解释 简写 file 装入想要调试的可执行文件 无 list 列出产生执行文件源代码的一部分 l next 执行一行源代码但不进入函数内部 n step 执行一行源代码而且进入函数内部 s run 执行当前被调试的程序 r continue 继续执行程序 c quit 终止gdb q print 输出当前指定变量的值 p break 在代码里设置断点 b info break 查看设置断点的信息 ib delete 删

【Linux】GDB调试工具

GDB调试工具 Linux中包含一个很强大的调试工具GDB(GNU Debuger),可以用它来调试C和C++程序. 一. GDB的主要功能有: 设置断点,当程序运行到断点处暂停 显示变量的值,可以打印或者监视某个变量,将变量的值显示出来 单步执行,GDB允许用户单步执行程序,可以跟踪进入函数和从函数中退出 运行时修改变量的值,GDB允许在调试状态下修改变量的值,此功能在测试程序的时候特别有用 路径跟踪,GDB可以将代码的路径打印出来,方便用户跟踪代码 线程切换,在调试多线程的时候,此种功能是必

Linux下常用调试工具总结

kdump+crash使用: kdump是linux下分析内核崩溃原因的工具.系统崩溃时,kdump用于转储运行内存,捕获当前运行信息,将此时内存中所有运行状态和数据信息收集到一个dump core文件中(一般是在var/crash中的vmcore),以便后续分析.(ps:虚拟机中设置的crash memory为256M,过大或过小都不行) crash是用于分析kdump生成的core文件的工具.crash常用的指令: (1)log:显示内核消息缓存区 (2)bt:显示内核崩溃前的堆栈信息(可以

LINUX下GDB反汇编和调试

Linux下的汇编与Windows汇编最大的不同就是第一个操作数是原操作数,第二个是目的操作数.而Windows下却是相反. 1. 基本操作指令 简单的操作数类型说明.一般有三种. (1)马上数操作数,也就是常数值.马上数的书写方式是"$"后面跟一个整数.比方$0x1F.这个会在后面的详细分析中见到非常多. (2)寄存器操作数,它表示某个寄存器的内容.用符号Ea来表示随意寄存器a,用引用R[Ea]来表示它的值.这是将寄存器集合看成一个数组R,用寄存器表示符作为索引. (3)操作数是存储

Linux下gdb调试(tui)

1 处于TUI模式的GDB 为了以TUI模式运行GDB,可以在调用GDB时在命令行上指定-tui选项,或者处于非TUI模式时在GDB中使用Ctrl+X+A组合键.如果当前处于TUI模式,后一种命令方式就会使你离开TUI模式. 在TUI模式中,GDB窗口划分为两个子窗口——一个用于输入GDB命令,而另一个用于查看源代码. 例如: 源代码为ins.c #include <stdio.h> int x[10], y[10], num_inputs, num_y = 0; void get_args(

Linux下GDB调试与对拍(先挖个坑)

应为NOIP要复赛在NOI-Linux下编写程序,所以被迫选择Vim+Gdb(主要是Guide太丑了). 虽然GUIDE的调试功能已经对付大多数的调试,反正学一学GDB的使用也没什么坏处. 1 生成调试信息 要调试C/C++的程序,首先在编译时,我们必须要把调试信息加到可执行文件中.使用编译器(cc/gcc/g++)的 -g 参数可以做到这一点.如: gcc -g hello.c -o hello g++ -g hello.cpp -o hello 如果没有-g,你将看不见程序的函数名.变量名,

Linux之gdb调试工具

1. 启动gdb 在使用gdb调试C/C++程序前,必须要使用gcc -g命令生成带有调试信息的可执行程序: $ gcc -g -o hello Hello.c 然后就可以使用gdb来对生成的hello二进制文件进行调试了. $ gdb hello gdb会首先在屏幕上答应一些其版本信息,然后显示提示符(gdb)等待用户指令. 2. 获取帮助 任何时候都能够使用help命令来查看帮助信息: (gdb) help 可以查看具体命令的帮助信息,如breakpoints (gdb)help break