GDB案例案例一:gdb基本过程
//simple.c
#include
#include
long func(int n);
int main(int argc, char *argv[])
{
printf("Entering main ...\n");
int i;
long result = 0;
for (i=1; i<=100; ++i)
{
result += i;
}
printf("result[1-100] = %ld\n", result);
printf("result[1-10] = %ld\n", func(10));
printf("Exiting main ...\n");
return 0;
}
long func(int n)
{
long sum = 0;
int i;
for (i=1; i<=n; ++i)
{
sum += i;
}
return sum;
}
gcc -Wall -g simple.c -o simple
gdb simple(或者gdb; file simple)
help
list
break 10
break func
info break
list 10
list func
单步step
单步next
until(跳出循环)
continue
finish(跳出函数)
案例二:run及参数
//simple.c
参数还可以包括输入输出重定向(<和>)和shell通配符(* ? [])for(i=0; i { printf("%s ", argv[i]; } printf("\n"); run(r) run arg1 arg2 Makefile .PHONY:clean all CC=gcc CFLAGS=-Wall -g BIN=simple main all:$(BIN) %.o:%.c $(CC) $(CFLAGS) -c $< -o $@ main:main.o search.o $(CC) $(CFLAGS) $^ -o $@ clean: rm -f *.o $(BIN) run a b c show args set args chg1 chg2(设置新的参数) run(再次运行) 案例三:list查看源码(多文件) //main.c search.c search.h main.c (1)#include (2)#include"search.h" (3) (4)int main(int argc, char *argv[]) (5){ (6)printf("Entering main ...\n"); (7)int i; (8)for (i=0; i (9){ (10)printf("%s ",argv[i]); (11)} (12)printf("\n"); (13)int a[10] = {1, 3, 8, 9, 8, 3, 8, 6, 9, 2}; (14)int key = 8; (15)int pos; (16)int count = 0; (17) (18)pos = 0; (19)while ((pos=seq_search(a, pos, 10, key)) != -1) (20){ (21)count++; (22)pos++; (23)} (24) (25)printf("%d occurs %d times in the list\n", key, count); (26)printf("Exiting main ...\n"); (27)return 0; (28)} Search.h #ifndef _SEARCH_H_ #define _SERACH_H_ int seq_search(int list[], int start, int n, int key); #endif// _SERACH_H_ Search.c #include"search.h" int seq_search(int list[], int start, int n, int key) { int i; for (i=start; i { if (list[i] == key) return i; } return -1; } list(l)查看最近的10行源代码 list fun查看fun函数源代码 list file:fun查看文件中的fun函数源代码list 2,10查看第2行到10行代码 list ,15查看最多到15行的位置 set listsize n show listsize list - 向前 list + 向后 makefile gdb main list list 1 list 10 list main list seq_search list search.c:seq_search 案例四:设置断点(多文件) //main.c search.c search.h break行号 break fun break file:行号 break file:fun break if watch expr 当expr值发生改变,程序停住delete break n删除断点 enable/disable break n 启用或禁止断点 break search.c:10 list search.c:10 break search.c:seq_search //条件断点simple.c break 15(long result =0 ;) run b if i=50 c p i (i=50) info locals info break(查看当前定义的断点和条件) //观察点(数据断点)simple.c watch i(i发生变化,程序就停) 观察点的用法与断点很相似,所有操作breakpoint的命令对watchpoint都适用。区别在于,断点是在CPU到某一 地址取指令时中断,而观察点是在CPU到某一地址读写数据时中断。 对watchpoint 案例五:单步调试 //simple.c continue(c) 运行至下一个断点 step(s)单步跟踪,进入函数 next(n)单步跟踪,不进入函数 finish 运行程序,直到当前函数完成返回,并打印函数返回时的堆栈地址和返回值及参数值等信息 until 运行程序直到退出循环体 break 15 (long result=0;) break 21 run continue step finish run(重新运行) next until 案例六:查看运行时数据 //simple.c int x=5; double z=2.5; char ch='q'; int arr1[] = {0,1,2,3,4,5,6,7,8,9}; int *arr2 = (int *)malloc(sizeof(int)*10); for(i=0;i<10;i++) { arr2[i]=i; } print查看变量值或表达式print /f ptype查看类型 print array查看数组 print *array@len查看动态内存 print x=2改变运行时数据 print $n 表示给定序号的前一个序号;如果没有数字n,默认当前序号为给定序号print $$n 表示给定序号的前两个序号;如果没有数字n,默认当前序号为给定序号 Break 13 (int arr1[] = {0,1,2,3,4,5,6,7,8,9};) ptype x ptype z ptype ch ptype “aaa” print arr1 打印整个数组元素 print arr1[2] 打印下标2的元素 print &arr1[2] 打印下标2的元素的地址 print &arr1[0] 打印数组首地址 print &arr1 打印数组首地址(和C不太一样) next next until print *arr2@10 查看数组arr2的10个元素 print *arr2@15 超出范围 print arr1@2 打印两组数组,一组合法,一组不合法 pinrt *arr1@2打印两个元素{0,1} print arr1[2]@2 打印下标2,3的元素{2,3} print i=1000 跳出循环;动态改变运行时数据 print result(没有加到100) 观察最后结果 全局变量(所有文件可见) 静态全局变量(当前文件可见) 局部变量(当前scope可见) 如果局部变量和全局变量发生冲突(重名),一般情况下局部变量会隐藏全局变量。 如果想查看全局变量的值或位于其他文件或其他函数的变量时,可以使用“::”操作符。Print Print Print 自动显示命令display 可以设置一些自动显示的变量,当程序停住时,或是单步跟踪时,这些变量会自动显示。display display/ display/ display/i $pc (/i表示输出格式为机器指令码;$pc环境变量,表示指令的地址) 查看内存命令examine (简写x) x/ x/4uh 0x48723 表示从内存地址0x48723读取内容,h表示以双字节为一个单位,4表示4个单位,u表示按十六进制显示 程序错误 (1)编译错误:编写运行时程序的时候没有符合语言规范导致编译错误 (2)运行时错误:编译器检查不出这种错误,但在运行时可能会导致程序崩溃 (3)逻辑错误:编译和运行都很顺利,但是程序没有干它该干的事情 案例七:程序错误调试 这个程序要实现逆序输出字符串hello,但是却没有任何输出 #include int main(void) { int i; char str[6] = "hello"; char reverse_str[6]=""; printf("%s\n", str); for(i=0;i<5;i++) { reverse_str[5-i] = str[i]; } printf("%s\n",reverse_str); return 0; } break 10 for(i=0;i<5;i++) print str[i] print str[0] step print reverse_str[5-i] print reverse_str step ... until print i print reverse_str ("\000olleh")\000八进制 找到错误reverse_str[5-i],改为reverse_str[4-i] 段错误是由于访问非法地址而产生的错误 (1)访问系统数据区,尤其是往系统保护的内存地址写数据,最常见就是个给一个指针以0地址 (2)内存越界(数组越界,变量类型不一致等)访问到不属于你的内存区域 案例八:段错误调试 //segerror.c #include #include void segfault() { int *p = NULL; *p = 100;uii } int main(void) { segfault(); /* char buf[1] = "a"; buf[10003] = 'A'; printf("%c\n", buf[10003]); */ return 0; } gdb segerror run 收到段错误SIGSEGV信号;看到第7行*p=100;出错 backtrace 回溯 frame list 7 //数组越界 #include #include int main(void) { char buf[1] = "a"; buf[10003] = 'A'; printf("%c\n", buf[10003]); return 0; } 如果改为buf[10],打印结果是A,看似正常,但是越界。 越界可能报错,可能不报错,比较难调试。 实例九:core文件调试 在程序崩溃时,一般会产生一个core文件。 该文件记录的是程序崩溃时的内存映像,并加入调试信息。 core文件生成的过程叫做core dump。 ulimti -c 查看core-dump状态;如果产生0,表示不产生core文件ulimti -a 查看所有参数 ulimit –c 数字 ulimti -c unlimited 用segfault 产生core文件 gdb segerror core文件 bt GDB基本使用方法 GDB是用来调试用户态程序的一款工具,可以追踪程序运行轨迹,打出调用栈,寄存器内容,查看内存等等 首先在编译时,我们必须要把调试信息加到可执行文件中。使用编译器(cc/gcc/g++)的-g 参数可以做到这一点。如果没有-g,你将看不见程序的函数名、变量名,所代替的全是运行时的内存地址。 启动GDB 直接找到gdb的路径执行就ok,进入GDB后可以输入help命令查看帮助信息 加载可执行文件启动 gdb executable-file set args 参数列表 以上两步等同于 gdb –args executable-file 参数列表 run或者start都可以启动调试 多用于调试启动阶段就异常的程序 调试正在运行的程序 以下三种形式都可以attach到正在运行的程序上调试 ps -ef | grep http www-data 24470 1 0 Jan17 ? 00:00:14 /usr/sbin/lighttpd gdb attach 24470 gdb --pid 24470 gdb -p 24470 设置断点 break -- Set breakpoint at specified line or function b func1 break func1 设置在func1处 b file:line 设置在文件的第几行处 b *0x指令地址设置在具体的某条汇编指令处 设置断点后,代码执行到func1处会被断住,方便我们查看当时的信息 打印调用栈 backtrace bt 如果你要查看栈下面层的详细信息 frame 栈中的层编号 查看所有断点 info break 删除断点 delete 断点号 如果不加断点号为删除全部断点 禁用断点 disable 断点号 启用断点 在gdb中,断点通常有三种形式 断点(BreakPoint): 在代码的指定位置中断,这个是我们用得最多的一种。设置断点的命令是break,它通常有如下方式: 可以通过info breakpoints [n]命令查看当前断点信息。此外,还有如下几个配套的常用命令: 观察点(WatchPoint): 在变量读、写或变化时中断,这类方式常用来定位bug。 捕捉点(CatchPoint): 捕捉点用来补捉程序运行时的一些事件。如:载入共享库(动态链接库)、C++的异常等。通常也是用来定位bug。 捕捉点的命令格式是:catch break 2.4 实例—使用gdb调试器 1.编写实例程序gcctest.c,见2.2小节的开头部分 2.编译 3.启动GDB,执行程序 启动gdb,进入gdb调试环境,可以使用gdb的命令对程序进行调试。 [root@localhost gdbtest txt]# gdb //启动gdb GNU gdb Fedora (6.8-27.el5) Copyright (C) 2008 Free Software Foundation, Inc. License GPLv3+: GNU GPL version 3 or later 淮海工学院计算机工程学 实验报告书 评语: 成绩:指导教师: 批阅时间:年月 实验目的与要求 1. 掌握Linux C 开发过程中的基本概念; 2. 掌握如GCC GDB等开发工具的使用。 二、实验内容 1. 将参考代码录入到文件中,编译执行后发现结果与预期不一致,请使用GDE调试, 完成字符串反序输出功能。 三、参考源代码 #include <> #include <> #include <> int reverse_str(char *string); int main (void) { char string[] = "Linux C Tools : GCC and GDB"; printf ("The original string is %s \n", string); reverse_str (string); } int reverse_str (char *str) { char *new_str; int i, size; size = strlen (str); if((new_str = (char *) malloc (size + 1)) == NULL) { return -1; } for (i = 0; i < size; i++) new_str[size - i] = str[i]; new_str[size+1] = ' '; printf("The reversed string is %s\n",new_str); free(new_str); return 0 ; } 四、实验步骤 步骤1. 编辑源代码 mkdir test1 cd test1 gedit (1) 使用gedit 编辑器,建议课外学习vim; (2) 分析代码中语句功能。 步骤 2. 编译源代码 Ubuntu下Vim+GCC+GDB安装及使用 一)安装 vim)打开命令行运行sudo apt-get install vim,并按提示输入管理员密码。 gcc+gdb)输入命令行运行 sudo apt-get install build-essential build-essential包含gcc和gdb等工具,是C语言的开发包。 安装完了可以执行 gcc --version 的命令来查看版本,输出如下: gcc (Ubuntu 4.8.2-19ubuntu1) 4.8.2 Copyright (C) 2013 Free Software Foundation, Inc. This is free software; see the source for copying conditions. There is NO warranty; not even for MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. 则表明安装好了。 二)常用编译命令选项 假设源程序文件名为test.c。 1. 无选项编译链接 用法:#gcc test.c 作用:将test.c预处理、汇编、编译并链接形成可执行文件。这里未指定输出文件,默认输出为a.out。 2. 选项 -o 用法:#gcc test.c -o test 作用:将test.c预处理、汇编、编译并链接形成可执行文件test。-o选项用来指定输出文件的文件名。 3. 选项 -E 用法:#gcc -E test.c -o test.i 作用:将test.c预处理输出test.i文件。 4. 选项 -S 用法:#gcc -S test.i 作用:将预处理输出文件test.i汇编成test.s文件。 5. 选项 -c 用法:#gcc -c test.s 作用:将汇编输出文件test.s编译输出test.o文件。 6. 无选项链接 用法:#gcc test.o -o test 附录A:GDB使用 1.基本命令 1)进入GDB #gdb test test是要调试的程序,由gcctest.c -g -o test生成。进入后提示符变为(gdb) 。 2)查看源码(gdb) l 源码会进行行号提示。 如果需要查看在其他文件中定义的函数,在l后加上函数名即可定位到这个函数的定义及查看附近的其他源码。或者:使用断点或单步运行,到某个函数处使用s进入这个函数。 3)设置断点(gdb) b 6 这样会在运行到源码第6行时停止,可以查看变量的值、堆栈情况等;这个行号是gdb的行号。 4)查看断点处情况(gdb) info b 可以键入"info b"来查看断点处情况,可以设置多个断点; 5)运行代码(gdb) r 6)显示变量值(gdb) p n 在程序暂停时,键入"p 变量名"(print)即可; GDB在显示变量值时都会在对应值之前加上"$N"标记,它是当前变量值的引用标记,以后若想再次引用此变量,就可以直接写作"$N",而无需写冗长的变量名; 7)观察变量(gdb) watch n 在某一循环处,往往希望能够观察一个变量的变化情况,这时就可以键入命令"watch"来观察变量的变化情况,GDB在"n"设置了观察点; 8)单步运行(gdb) n 9)程序继续运行(gdb) c 使程序继续往下运行,直到再次遇到断点或程序结束; 10)退出GDB (gdb) q 2.断点调试 break+设置断点的行号,break n,在n行处设置断点; tbreak+行号或函数名,tbreak n/func,设置临时断点,到达后被自动删除; break+filename+行号, break main.c:10,用于在指定文件对应行设置断 GDB命令大全 GDB的使用 当程序出错并产生core 时 快速定位出错函数的办法 gdb 程序名 core文件名(一般是core,也可能是core.xxxx) 调试程序使用的键 r run 运行.程序还没有运行前使用 c cuntinue 继续运行。运行中断后继续运行 q 退出 kill 终止调试的程序 h help 帮助 b breakpoint 设置断点。 用法: b 函数名对此函数进行中断 b 文件名:行号对此文件中指定行中断.如果是当前文件,那么文件名与:号可以省略 看当前断点数使用info break.禁止断点disable 断点号.删除delete 断点号. l list 列出代码行。一次列10 行。连接使用list将会滚动显示. 也可以在list 后面跟上文件名:行号 watch 观察一个变量的值。每次中断时都会显示这个变量的值 p print 打印一个变量的值。与watch不同的是print只显示一次 这里在顺便说说如何改变一个 value. 当你下指令 p 的时候,例如你用 p b, 这时候你会看到 b 的 value, 也就是上面的 $1 = 15. 你也同样可以用 p 来改变一个 value, 例如下指令 p b = 100 试试看, 这时候你会发现, b 的 value 就变成 100 了:$1 = 100. 网上抄录 基本的使用方法简介 前言 程序代码中的错误可分为数类,除了最容易除错的语法错误,编译程序会告诉你错误所在外,大部分的错误都可以归类为执行时错误。GDB 的功能便是寻找执行时错误。如果没有除错程序,我们只能在程序中加入输出变量值的指令来了解程序执行的状态。有了 GDB 除错程序,我们可以设定在任何地方停止程序的执行,然后可以随意检视变量值及更动变量,并逐行执行程序。 一个除错程序执行的流程通常是这样的: 1. 进入除错程序并指定可执行文件。 2. 指定程序代码所在目录。 3. 设定断点后执行程序。 4. 程序于断点中断后,可以 (1)检视程序执行状态;检视变量值或变更变量值 (2) 逐步执行程序,或是全速执行程序到下一个断点或是到程序结束为止。 5. 离开除错程序。 以下将分为下列数项分别介绍: ARM汇编指令调试方法 学习ARM 汇编时,少不了对ARM 汇编指令的调试。作为支持多语言的 调试器,gdb 自然是较好的选择。调试器工作时,一般通过修改代码段的内容 构造trap 软中断指令,实现程序的暂停和程序执行状态的监控。为了在x86 平 台上执行ARM 指令,可以使用qemu 模拟器执行ARM 汇编指令。一、准备ARM 汇编程序首先,我们构造一段简单的ARM 汇编程序作为测试代码 main.s。 .globl _start_start:mov R0,#0swi0x00901 以上汇编指令完成了0 号系统调用exit 的调用。mov 指令将系统调用号传入寄存器R0,然后使用0x00901 软中断 陷入系统调用。 为了运行ARM 汇编代码,需要使用交叉编译器arm-linux-gcc 对ARM 汇编 代码进行编译。下载交叉编译器安装完毕后,对ARM 汇编代码进行编译。 arm-linux-gcc main.s -o main -nostdlib 编译选项-nostdlib 表示不使用任何运行时库文件,编译生成的可执行文件main 只能在ARM 体系结构的系统上运行。二、编译安装qemu 模拟器为了x86 的Linux 系统内运行ARM 体系结构的可 执行程序,需要安装qemu 模拟器。 首先下载qemu 源码,然后保证系统已经安装了flex 和bison。 编译安装qemu。 ./configure --prefix=/usrsudo make && make install 然后使用qemu 的ARM 模拟器执行ARM 程序。 qemu ./main 三、编译安装arm-gdb 为了调试ARM 程序,需要使用gdb 的源码编译生成arm-gdb。 首先下载gdb 源代码,编译安装。 Linux下GDB调试命令_1 2008-11-21 18:39 GDB是GNU开源组织发布的一个强大的UNIX下的程序调试工具,不过现在在Linux下也可以用了。它使你能在程序运行时观察程和内存的使用情况。Linux不比Windows,没有那么多方便的图形界面方式的,像.Net、Eclipse等IDE的调试器。但上天逼着我在Li 软件,用了一段时间,你会发现GDB这个调试工具一点不比其它的差,所谓“寸有所长,尺有所短”就是这个道理。 一般来说,我可以用GDB来: ?加载程序 ?设置监视点、断点、入口条件等 ?动态的改变你程序的执行环境 ?单步调试、追踪 一、加载文件 启动GDB的方法有以下几种: 1、>gdb [exe] 2、>gdb pid [pid] GDB启动时,可以加上一些GDB的启动开关,详细的开关可以用gdb -help查看。我在下面只例举一些比较常用的参数: -symbols -s 从指定文件中读取符号表。 -se file 从指定文件中读取符号表信息,并把他用在可执行文件中。 -core -c 调试时core dump的core文件。 -directory -d 加入一个源文件的搜索路径。默认搜索路径是环境变量中PATH所定义的路径。 二、运行命令 当以gdb 方式启动gdb后,gdb会在PATH路径和当前目录中搜索的源文件。 在gdb中,运行程序使用r或是run命令。程序的运行,你有可能需要设置下面四方面的事。 1、程序运行参数。 set args 可指定运行时参数。(如:set args 10 20 30 40 50) show args 命令可以查看设置好的运行参数。 2、运行环境。 path 可设定程序的运行路径。 show paths 查看程序的运行路径。 set environment varname [=value] 设置环境变量。如:set env USER=hchen show environment [varname] 查看环境变量。 3、工作目录。 cd 相当于shell的cd命令。 pwd 显示当前的所在目录。 4、程序的输入输出。 GDB调试及实例 一:列文件清单 1.List (gdb) list line1,line2 二:执行程序 要想运行准备调试的程序,可使用run命令,在它后面可以跟随发给该程序的任何参数,包括标准输入和标准输出说明符(<和>)和外壳通配符(*、?、[、])在内。 如果你使用不带参数的run命令,gdb就再次使用你给予前一条run命令的参数,这是很有用的。 利用set args 命令就可以修改发送给程序的参数,而使用show args 命令就可以查看其缺省参数的列表。 (gdb)set args –b –x (gdb) show args backtrace命令为堆栈提供向后跟踪功能。 Backtrace 命令产生一张列表,包含着从最近的过程开始的所以有效过程和调用这些过程的参数。 三:显示数据 利用print 命令可以检查各个变量的值。 (gdb) print p (p为变量名) whatis 命令可以显示某个变量的类型 (gdb) whatis p type = int * print 是gdb的一个功能很强的命令,利用它可以显示被调试的语言中任何有效的表达式。表达式除了包含你程序中的变量外,还可以包含以下内容: l 对程序中函数的调用 (gdb) print find_entry(1,0) l 数据结构和其他复杂对象 (gdb) print *table_start $8={e=reference=’\000’,location=0x0,next=0x0} l 值的历史成分 (gdb)print $1 ($1为历史记录变量,在以后可以直接引用$1 的值) l 人为数组 人为数组提供了一种去显示存储器块(数组节或动态分配的存储区)内容的方法。早期的调试程序没有很好的方法将任意的指针换成一个数组。就像对待参数一样,让我们查看内存中在变量h后面的10个整数,一个动态数组的语法如下所示: base@length 因此,要想显示在h后面的10个元素,可以使用h@10: (gdb)print h@10 $13=(-1,345,23,-234,0,0,0,98,345,10) 1. 本文介绍使用gdb调试程序的常用命令。 主要内容: [简介] [举例] [其他] [简介] ============= GDB是GNU开源组织发布的一个强大的UNIX下的程序调试工具。如果你是在UNIX平台下做软件,你会发现GDB这个调试工具有比VC、BCB的图形化调试器更强大的功能。同时GDB也具有例如ddd这样的图形化的调试端。 一般来说,GDB主要完成下面四个方面的功能: (1)启动你的程序,可以按照你的自定义的要求随心所欲的运行程序。 (2)可让被调试的程序在你所指定的调置的断点处停住。(断点可以是条件表达式) (3)当程序被停住时,可以检查此时你的程序中所发生的事。 (4)动态的改变你程序的执行环境。 [举例] ============= *启动gdb $gdb 这样可以和gdb进行交互了。 *启动gdb,并且分屏显示源代码: $gdb -tui 这样,使用了'-tui'选项,启动可以直接将屏幕分成两个部分,上面显示源代码,比用list方便多了。这时候使用上下方向键可以查看源代码,想要命令行使用上下键就用[Ctrl]n和[Ctrl]p. *启动gdb调试指定程序app: $gdb app 这样就在启动gdb之后直接载入了app可执行程序,需要注意的是,载入的app程序必须在编译的 时候有gdb调试选项,例如'gcc -g app app.c',注意,如果修改了程序的源代码,但是没有编译,那么在gdb中显示的会是改动后的源代码,但是运行的是改动前的程序,这样会导致跟踪错乱的。 *启动程序之后,再用gdb调试: $gdb 常用的gdb命令 backtrace 显示程序中的当前位置和表示如何到达当前位置的栈跟踪(同义词:where)breakpoint 在程序中设置一个断点 cd 改变当前工作目录 clear 删除刚才停止处的断点 commands 命中断点时,列出将要执行的命令 continue 从断点开始继续执行 delete 删除一个断点或监测点;也可与其他命令一起使用 display 程序停止时显示变量和表达时 down 下移栈帧,使得另一个函数成为当前函数 frame 选择下一条continue命令的帧 info 显示与该程序有关的各种信息 jump 在源程序中的另一点开始运行 kill 异常终止在gdb 控制下运行的程序 list 列出相应于正在执行的程序的原文件内容 next 执行下一个源程序行,从而执行其整体中的一个函数 print 显示变量或表达式的值 pwd 显示当前工作目录 pype 显示一个数据结构(如一个结构或C++类)的内容 quit 退出gdb reverse-search 在源文件中反向搜索正规表达式 run 执行该程序 search 在源文件中搜索正规表达式 set variable 给变量赋值 signal 将一个信号发送到正在运行的进程 step 执行下一个源程序行,必要时进入下一个函数 undisplay display命令的反命令,不要显示表达式 until 结束当前循环 up 上移栈帧,使另一函数成为当前函数 watch 在程序中设置一个监测点(即数据断点) whatis 显示变量或函数类型 GDB命令分类详解 一:列文件清单 (2) 二:执行程序 (2) 三:显示数据 (2) 四:断点(breakpoint) (3) 五.断点的管理 (3) 六.变量的检查和赋值 (4) 七.单步执行 (4) 八.函数的调用 (4) 九.机器语言工具 (4) 十.信号 (4) 十一.原文件的搜索 (5) 十二. UNIX接口 (5) 十三. 命令的历史 (5) 十四. GDB帮助 (5) 十五. GDB多线程 (6) 十六. GDB使用范例 (7) 一:列文件清单 1.List (gdb) list line1,line2 二:执行程序 要想运行准备调试的程序,可使用run命令,在它后面可以跟随发给该程序的任何参数,包括标准输入和标准输出说明符(<和>)和外壳通配符(*、?、[、])在内。 如果你使用不带参数的run命令,gdb就再次使用你给予前一条run命令的参数,这是很有用的。 利用set args 命令就可以修改发送给程序的参数,而使用show args 命令就可以查看其缺省参数的列表。 (gdb)set args –b –x (gdb) show args backtrace命令为堆栈提供向后跟踪功能。 Backtrace 命令产生一张列表,包含着从最近的过程开始的所以有效过程和调用这些过程的参数。 三:显示数据 利用print 命令可以检查各个变量的值。 (gdb) print p (p为变量名) whatis命令可以显示某个变量的类型 (gdb) whatis p type = int * print 是gdb的一个功能很强的命令,利用它可以显示被调试的语言中任何有效的表达式。表达式除了包含你程序中的变量外,还可以包含以下内容: 一,GDB调试器简介 GDB是Linux下的常用调试器,主要用于调试源代码、调试运行中的进程和查看core dump文件。Linux下的调试器主要有gdb、cgdb、ddd、eclipse。GDB调试器的运行速度快、能够进行源代码同步显示。 使用-tui 选项开启gdb命令输入和源代码的分屏显示,tui即Terminal User Interface。 二,GDB常用调试命令 a)调试可执行文件 以源代码为/home/zebra/目录下的test.c文件产生的可执行文件test为例(可执行文件使用gcc进行编译,并使用-g选项以产生调试信息),进行命令的说明(详细源代码参见第三部分:三,调试实例分析 )。 gdb调试源代码流程: 1,开启gdb程序,即运行如下命令:gdb -q (-q用以使得gdb不输出gdb程序的版本等信息)2,指定调试的二进制文件:file test 3,list查看源代码 4,设定断点breakpoint main breakpoint sub 上述分别在main函数和sub函数处设定了断点。 断点可以设置在任意已知源代码文件的某一行,某一个函数,同时可以指定是设置在哪个/哪些线程上(见下边描述)。 5,运行可执行文件: run 6,这样程序会运行到断点处停止下来,gdb会打印当前断点的信息。 7,使用s 或者n进行单步调试。 s即step,n即next都是执行一条语句,然后停下来。 如果想执行一条汇编语句,则可以使用si ,ni,即step instruction,next instruction。 8,bt命令查看当前的调用栈,bt即backtrace。 9,info frame查看函数帧信息。 10,frame n 进入某个函数帧(编号为n) 11,info 命令可以对当前的函数帧的寄存器、局部变量、函数的参数进行查看。 info register;info local;info args。 12,disassemble对当前函数对应的二进制进行反汇编。 13,x/nfu address 查看内存其中address是内存开始的地址,从该地址向高地址增加, x是examinate的缩写,n表示重复次数,f表示输出格式,u表示内存大小的单位(默认是字,即4个字节)。 一般我都用x/nx address,即打印n个从address开始的内存,每个是4字节,以十六进制打印。14,continue,执行至该函数退出 15,info threads,显示当前可调试的所有线程 16,thread (转贴)linux 下的软件开发之GCC,GDB用法篇 -|tinylee 发表于 2005-8-22 1:02:00 在为Linux开发应用程序时,绝大多数情况下使用的都是C语言,因此几乎每一位Linux程序员面临的首要问题都是如何灵活运用C编译器。目前Linux下最常用的C语言编译器是GCC(GNU Compiler Collection),它是GNU项目中符合ANSI C标准的编译系统,能够编译用C、C++和Object C等语言编写的程序。GCC不仅功能非常强大,结构也异常灵活。最值得称道的一点就是它可以通过不同的前端模块来支持各种语言,如Java、Fortran、Pascal、Modula-3和Ada等。 开放、自由和灵活是Linux的魅力所在,而这一点在GCC上的体现就是程序员通过它能够更好地控制整个编译过程。在使用GCC编译程序时,编译过程可以被细分为四个阶段: ◆ 预处理(Pre-Processing) ◆ 编译(Compiling) ◆ 汇编(Assembling) ◆ 链接(Linking) Linux程序员可以根据自己的需要让GCC在编译的任何阶段结束,以便检查或使用编译器在该阶段的输出信息,或者对最后生成的二进制文件进行控制,以便通过加入不同数量和种类的调试代码来为今后的调试做好准备。和其它常用的编译器一样,GCC也提供了灵活而强大的代码优化功能,利用它可以生成执行效率更高的代码。 GCC提供了30多条警告信息和三个警告级别,使用它们有助于增强程序的稳定性和可移植性。此外,GCC 还对标准的C和C++语言进行了大量的扩展,提高程序的执行效率,有助于编译器进行代码优化,能够减轻编程的工作量。 GCC起步 在学习使用GCC之前,下面的这个例子能够帮助用户迅速理解GCC的工作原理,并将其立即运用到实际的项目开发中去。首先用熟悉的编辑器输入清单1所示的代码: 清单1:hello.c #i nclude 1 虚拟机VMware6.5、RedHat安装及Linux基本命令 1.1 GCC、GDB的安装 虚拟将上安装RedHat后,在Linux环境下编辑和编译C\C++需要GCC、GDB编译,调试,Linux环境下输入gcc -v于gdb –v可以查看所装系统是否装有gcc与gdb。如果没有显示其所装版本,可以在Redhat 的RPMs包中找到相应版本的gcc与gdb的rmp安装文件。具体方法是vm->Removable Devices->CD\DVD->Connect. 把RedHat的镜像文件添加到use iso image file:下,点击OK,在VMware界面上出现以个光盘的标志双击后RedHat->RAMPS,选择要安装的GCC、与GDB文件。 注:不能直接用GCC变异C++文件,最好使用G++编译。 1.2 Linux基本命令 Linux常用命令全集:https://www.doczj.com/doc/9f14572903.html,/special/linuxcom/ 2 GCC、GDB的使用及基本指令 2.1 Linux环境下vi编辑器的基本使用方法 VMware界面上右键->open terminal 界面中输入vi 回车([jkl@localhost ~]$ vi) 在vi编辑器下输入要编辑的程序: #include 3.5.2 Gdb基本命令 Gdb的命令可以通过查看help进行查找,由于Gdb的命令很多,因此Gdb的he lp将其分成了很多种类(class),用户可以通过进一步查看相关class找到相应命令。如下所示: (gdb) help List of classes of commands: aliases -- Aliases of other commands breakpoints -- Making program stop at certain points data -- Examining data files -- Specifying and examining files internals -- Maintenance commands … Type "help" followed by a class name for a list of commands in that class. Type "help" followed by command name for full documentation. Command name abbreViations are allowed if unambiguous. 上述列出了Gdb各个分类的命令,注意底部的加粗部分说明其为分类命令。接下来可以具体查找各分类种的命令。如下所示: (gdb) help data Examining data. List of commands: call -- Call a function in the program delete display -- Cancel some expressions to be displayed when program stops delete mem -- Delete memory region GDB 是GNU开源组织发布的一个强大的UNIX下的程序调试工 具。或许 ,各位比较喜欢那种图形界面方式的,像VC、BCB等IDE的调试,但如 果你是在 UNIX平台下做软件,你会发现GDB这个调试工具有比VC、 BCB的图形化调试器更强大的功能。所谓“寸有所长,尺有所短” 就 是这个道理。 一般来说,GDB主要帮忙你完成下面四个方面的功能: 1、启动你的程序,可以按照你的自定义的要求随心所欲的运行程序。 2、可让被调试的程序在你所指定的调置的断点处停住。(断点可以是条件表达式) 3、当程序被停住时,可以检查此时你的程序中所发生的事。 4、动态的改变你程序的执行环境。 从上面看来,GDB和一般的调试工具没有什么两样,基本上也是完成 这些功能,不过在细节上,你会发现GDB这个调试工具的强大, 大家 可能比较习惯了图形化的调试工具,但有时候,命令行的调试工具却 有着图形化工具所不能完成的功能。让我们一一看来。 源程序:tst.c 1 #include GDB是GNU开源组织发布的一个强大的UNIX下的程序调试工具。如果你是在 UNIX平台下做软件,你会发现GDB这个调试工具有比VC、 BCB的图形化调试器更强大的功能。同时GDB也具有例如ddd这样的图 形化的调试端。 一般来说,GDB主要完成下面四个方面的功能: (1)启动你的程序,可以按照你的自定义的要求随心所欲的运行程序。 (2)可让被调试的程序在你所指定的调置的断点处停住。(断点可以是条 件表达式) (3)当程序被停住时,可以检查此时你的程序中所发生的事。 (4)动态的改变你程序的执行环境。 兴趣是最好的老师,这里先整理总结一下在调试的过程中经常遇到的问题。带着这些问题进行学习和实践可以有助于加深印象 (1)如何打印变量的值?(print var) (2)如何打印变量的地址?(print &var) (3)如何打印地址的数据值?(print *address) (4)如何查看当前运行的文件和行?(backtrace) (5)如何查看指定文件的代码?(list file:N) (6)如何立即执行完当前的函数,但是并不是执行完整个应用程序?(finish) (7)如果程序是多文件的,怎样定位到指定文件的指定行或者函数?(list file:N) (8)如果循环次数很多,如何执行完当前的循环?(until) (9)多线程如何调试?(???) [举例] ============= *启动gdb $gdb 这样可以和gdb进行交互了。 *启动gdb,并且分屏显示源代码: $gdb -tui 这样,使用了'-tui'选项,启动可以直接将屏幕分成两个部分,上面显示源代码,比用list方便多了。这时候使用上下方向键可以查看源代码,想要命令行使用上下键就用[Ctrl]n和[Ctrl]p. *启动gdb调试指定程序app: $gdb app 这样就在启动gdb之后直接载入了app可执行程序,需要注意的是,载入的app程序必须在编译的时候有gdb调试选项,例如'gcc -g app app.c',注意,如果修改了程序的源代码,但是没有编译,那么在gdb中显示的会是改动后的源代码,但是运行的是改动前的程序,这样会导致跟踪错乱的。 *启动程序之后,再用gdb调试: $gdb GDB基本使用方法
如何高效使用GDB断点
实例—使用gdb调试器
实验一LinuxC编程工具GCC和GDB
Ubuntu下Vim GCC GDB安装及使用
GDB常用命令
GDB命令大全
ARM汇编指令调试方法
linux环境下的调试命令
GDB调试及实例
GDB基本命令
LINUX gdb调试命令手册
用GDB调试程序--调试器GDB常用功能
linux软件开发之GCC,GDB用法篇
linux、GCC、GDB学习总结
gdb基本命令
GDB使用说明书
GDB调试