实验三、用GDB调试程序的bug
- 格式:docx
- 大小:196.36 KB
- 文档页数:4
第 26 卷 第 5 期 2005 年 9 月微 计 算 机 应 用M I CROCO M P U I ER A P P L ICA T I ON S Vo l . 26 No . 5 Sep t . 20053远程调试工具 G dbstub 的分析与改进3李红卫 王树亮( 江苏技术师范学院 常州 213001)摘 要 :分析了利用 Gdb st ub 远程调试 L i n ux 内核的原理 ,提出了对 Gdbst u b 的改进方法 ,首先实现了目标机上 运行的程序在调试模式和正常运行模式之间的切换 ,其次 ,在 G db st u b 中增加了测定程序段运行时间的功能 。
关键词 :L i nux 远程调试 G dbstub 异常处理 时间戳Analysis an d Improe v e m ent of R e mote Debugging T ool G dbstubL I Ho n gwei , WA N G Sh ulia n g(J iangSu Teacher s U ni ver sit y of Technolo g y ,Chang Zho u , 213001 , Chi na )Abstract : In t h i s p ap e r , we a n alyzed t h e p r incip le of G dbst u b which i s used fo r remo t e debugging L i n ux ker n el , a nd p re sent ed t he imp r o v ement met h o ds fo r gdbst ub. Fi r st ly , we realized t he f unctio n of swit chi ng bet ween t h e d eter 2 min mg mo de and no r mal mo de o n t he t a r get . S eco ndly , we a dde d a p reci setiming f unctio n fo r deter mi n ing t h e r u nning ti m e of a p r ocedure ’s in gdb st u b.key w ords :L i nux , remo t e debugging , G db st u b ,excep t io n ha n dli n g ; t ime st a mp须对目标机上所发生的所有异常进行统一管理 ,在 st a r t _ k er 2 nel () 函数中通过调用 t rap _init ( ) 函数设置各种入口地址 ,如 异常事件 处 理 程 序 入 口 、系 统 调 用 入 口 等 。
经典的GDB调试命令,包括查看变量,查看内存经典的GDB调试命令,包括查看变量,查看内存在你调试程序时,当程序被停住时,你可以使⽤print命令(简写命令为p),或是同义命令inspect来查看当前程序的运⾏数据。
print命令的格式是:printprint /是表达式,是你所调试的程序的语⾔的表达式(GDB可以调试多种编程语⾔),是输出的格式,⽐如,如果要把表达式按16进制的格式输出,那么就是/x。
⼀、表达式print和许多GDB的命令⼀样,可以接受⼀个表达式,GDB会根据当前的程序运⾏的数据来计算这个表达式,既然是表达式,那么就可以是当前程序运⾏中的const常量、变量、函数等内容。
可惜的是GDB不能使⽤你在程序中所定义的宏。
表达式的语法应该是当前所调试的语⾔的语法,由于C/C++是⼀种⼤众型的语⾔,所以,本⽂中的例⼦都是关于C/C++的。
(⽽关于⽤GDB 调试其它语⾔的章节,我将在后⾯介绍)在表达式中,有⼏种GDB所⽀持的操作符,它们可以⽤在任何⼀种语⾔中。
@是⼀个和数组有关的操作符,在后⾯会有更详细的说明。
::指定⼀个在⽂件或是⼀个函数中的变量。
{}表⽰⼀个指向内存地址的类型为type的⼀个对象。
⼆、程序变量在GDB中,你可以随时查看以下三种变量的值:1. 全局变量(所有⽂件可见的)2. 静态全局变量(当前⽂件可见的)3. 局部变量(当前Scope可见的)如果你的局部变量和全局变量发⽣冲突(也就是重名),⼀般情况下是局部变量会隐藏全局变量,也就是说,如果⼀个全局变量和⼀个函数中的局部变量同名时,如果当前停⽌点在函数中,⽤print显⽰出的变量的值会是函数中的局部变量的值。
如果此时你想查看全局变量的值时,你可以使⽤::操作符:file::variablefunction::variable可以通过这种形式指定你所想查看的变量,是哪个⽂件中的或是哪个函数中的。
例如,查看⽂件f2.c中的全局变量x的值:gdb) p 'f2.c'::x当然,::操作符会和C++中的发⽣冲突,GDB能⾃动识别::是否C++的操作符,所以你不必担⼼在调试C++程序时会出现异常。
gdb使用教程GDB是GNU调试器的缩写,是一个功能强大的命令行调试工具,用于帮助开发人员在调试过程中定位和修复程序中的错误。
以下是GDB的使用教程:1. 编译程序时添加调试信息:在使用GDB进行调试之前,需要确保程序在编译时包含了调试信息。
可以通过在编译命令中添加`-g`选项来实现。
例如:`gcc -g main.c -o main`。
2. 启动GDB:在命令行中输入`gdb`命令,然后输入可执行文件的路径作为参数。
例如:`gdb ./main`。
3. 设置断点:断点是在程序执行到指定位置时停下来的标记。
可以使用`break`命令来设置断点。
例如:`break main`可以在`main`函数的开头设置一个断点。
4. 开始执行程序:使用`run`命令来运行程序。
例如:`run`。
5. 执行程序并停在断点处:当程序开始运行后,会在达到断点处停下来等待输入。
此时可以使用一些GDB命令来检查程序的状态,如查看变量的值、栈帧等。
6. 单步执行:使用`next`命令来逐行执行程序。
例如:`next`。
7. 跳出函数:使用`finish`命令可以跳出当前正在执行的函数,并停在调用该函数的上一个函数中。
8. 继续执行:使用`continue`命令可以接着执行程序直到下一个断点或程序结束。
9. 查看变量的值:使用`print`或简写的`p`命令可以查看变量的值。
例如:`print i`可以查看变量`i`的值。
10. 修改变量的值:使用`set`命令可以修改变量的值。
例如:`set i = 10`可以将变量`i`的值修改为10。
11. 查看函数调用栈:使用`backtrace`或简写的`bt`命令可以查看函数调用栈。
12. 退出GDB:使用`quit`命令可以退出GDB。
以上是一些常用的GDB命令,使用GDB进行调试时还有很多其他的功能和命令可以使用,可以通过阅读GDB的文档来更详细地了解。
gdb 调试函数
要调试一个函数,你需要以下步骤:1. 使用`gdb` 命令行工具启动你的程序:`gdb <executable>`,其中`<executable>` 是你要调试的可执行文件。
2. 设置断点:使用`break` 命令在你要调试的函数的位置设置断点。
例如,如果你要调试的函数是`my_function()`,可以使用`break my_function` 来设置断点。
3. 启动程序:使用`run` 命令启动程序,然后程序将在断点处停止执行。
4. 执行程序:使用`next` 命令按行执行代码,或使用`step` 命令进入函数内部执行。
5. 在调试过程中查看变量的值:使用`print` 命令来查看变量的值。
例如,可以使用`print variable_name` 来查看变量`variable_name` 的值。
6. 继续执行程序:使用`continue` 命令继续执行程序,直到下一个断点或程序结束。
7. 在调试结束后退出`gdb`:使用`quit` 命令退出`gdb`。
这些是基本的
`gdb` 调试函数的使用方法。
你还可以使用其他命令来查看堆栈信息、设置条件断点、跳到指定行等。
可以使用`help` 命令来获取更多有关`gdb` 命令的信息。
gdb条件断点字符串【一、GDB简介】GDB(GNU Debugger)是一款强大的开源调试工具,主要用于调试C、C++等编程语言编写的程序。
GDB提供了一种交互式的方式,允许程序员在运行时观察程序状态、设置断点、单步执行代码等。
在GDB中,条件断点是一个非常重要的功能,可以帮助我们更加高效地调试程序。
【二、条件断点概念】条件断点是指在程序运行过程中,当满足特定条件时,自动暂停程序执行,以便调试器可以进行检查。
与普通断点不同,条件断点不是在固定的代码位置设置的,而是在满足条件时触发。
这使得我们在调试程序时更加灵活,可以更快地找到问题所在。
【三、设置条件断点的方法】在GDB中设置条件断点非常简单。
首先,使用`break`命令设置一个断点,如:`break filename.c`。
然后,使用`if`命令添加条件,例如:`if (condition) break`。
最后,使用`continue`命令继续执行程序,当条件满足时,程序将自动暂停。
【四、条件断点的应用场景】1.观察程序运行过程中某个变量的值是否符合预期。
2.检查函数调用栈,找出程序出现问题的位置。
3.在特定条件下暂停程序,便于排查问题。
4.结合`continue`命令,有选择地执行代码块。
【五、实战案例分享】假设我们有一个程序,通过输入输出一个数组的大小,然后循环遍历数组,对每个元素进行加1操作。
但程序中存在一个bug,导致输出的结果不正确。
我们可以使用条件断点来定位问题。
1.首先,使用`gdb`命令启动GDB。
2.设置断点:`break main`3.运行程序,直到进入循环部分,此时暂停程序。
4.设置条件断点:`break (array[i] + 1 != array[i + 1])`5.继续执行程序,当条件满足时,程序暂停。
6.检查变量值,发现array[i]和array[i + 1]的值,从而找出问题所在。
【六、总结与建议】条件断点是GDB中一个非常实用的功能,可以帮助我们在调试程序时更加高效地定位问题。
gdb break用法
GDB(GNU Debugger)是一款功能强大的调试工具,它支持在程序运行时设置和删除断点,以帮助开发人员检查程序的执行情况和排查错误。
以下是GDB中关于`break`命令的用法介绍:
- `break`:不带参数时,在所选栈帧中执行的下一条指令处设置断点。
- `break <function>`:在函数体入口处打断点。
- `break <line>`:在当前源码文件指定行的开始处打断点。
- `break -N`或`break +N`:在当前源码行前面或后面的N行开始处打断点,N为正整数。
- `break <filename:line>`:在源码文件`filename`的`line`行处打断点。
- `break <filename:function>`:在源码文件`filename`的`function`函数入口处打断点。
- `break <address>`:在程序指令的地址处打断点。
- `break ... if <cond>`:设置条件断点,... 代表上述参数之一(或无参数),cond 为条件表达式,仅在`cond`值非零时停住程序。
你可以根据需要选择合适的断点设置方式,以帮助你在调试程序时更加高效和便捷。
如需了解更多关于GDB的信息,请参考相关文档或技术资料。
1执行socket文件时,出现段错误(core dumped)产生段错误就是访问了错误的内存段,一般是你没有权限,或者根本就不存在对应的物理内存,尤其常见的是访问0地址.解决方法:利用gdb逐步查找段错误:首先我们需要一个带有调试信息的可执行程序,所以我们加上―-g -rdynamic"的参数进行编译,然后用gdb调试运行这个新编译的程序,具体步骤如下:1、gcc -g -rdynamic d.c2、gdb ./a.out3、r这样就找到了出错位臵。
然后在相应位臵修改。
2linux 段错误如何调试linux下的c程序常常会因为内存访问错误等原因造成segment fault(段错误)此时如果系统core dump功能是打开的,那么将会有内存映像转储到硬盘上来,之后可以用gdb对core文件进行分析,还原系统发生段错误时刻的堆栈情况。
这对于我们发现程序bug很有帮助。
使用ulimit -a可以查看系统core文件的大小限制;使用ulimit -c [kbytes]可以设臵系统允许生成的core文件大小。
ulimit -c 0 不产生core文件ulimit -c 100 设臵core文件最大为100kulimit -c unlimited 不限制core文件大小步骤:1、当发生段错误时,我们查看ulimit -a (core file size (blocks, -c) 0)并没有文件,2、设臵:ulimit -c unlimited 不限制core文件大小3.、运行程序,发生段错误时会自动记录在core中4、test]$ ls -al core.* 在那个文件下(-rw------- 1 leconte leconte 139264 01-06 22:3 1 core.2065)5、使用gdb 运行程序和段错误记录的文件。
(est]$ gdb ./test core.2065)6、会提哪行有错。
北京林业大学2012学年—2013学年第二学期 Linux应用实验任务书专业名称:信息管理与信息系统班级:姓名:学号:实验题目:实验四 gcc和gdb的基本使用实验环境: Red Hat Linux 9 实验目的:通过调试一个有问题的程序,进一步熟练使用Vi 操作,而且熟练掌握Gcc 编译及Gdb 的调试命令,通过对有问题程序的跟踪调试,进一步提高发现问题和解决问题的能力。
实验内容:Gdb调试题目:(1)使用Vi 编辑器,将以下代码输入到名为greet.c 的文件中。
此代码的原意为输出倒序main函数中定义的字符串,但结果显示没有输出。
代码如下所示:(2)使用Gcc 编译这段代码。
(3)运行生成的可执行文件,观察运行结果。
(4)使用Gdb 调试程序,通过设置断点、单步跟踪,一步步找出错误所在。
(5)纠正错误,更改源程序并得到正确的结果。
实验步骤:(1)在工作目录上新建文件greet.c,并用Vi 启动:vi greet.c。
(2)在Vi 中输入以上代码。
(3)在Vi 中保存并退出:wq。
(4)用Gcc 编译:(5)运行greet:./greet,输出为:可见,该程序没有能够倒序输出(6)启动Gdb 调试:(7)查看源代码并进行调试。
使用list查看源代码:将原来有错的程序经过Gdb调试,找出问题所在,并修改源代码,输出正确的倒序显示字符串的结果。
实验步骤中请适当截图。
GNU调试器是一个功能非常强大的工具。
要了解更加详尽的知识,建议阅读GNU调试器手册。
在执行完for循环后设置一个断点,以便查看是否在赋值时出了问题设置完断点后运行,到断点设置处停止:发现的问题:查看赋值后string2中的数据,发现string2【0】被赋值了字符串的结尾标志“\0”,因此,在后面执行printf 输出时,由于第一个字符就是结束标志,因此,不会输出后面倒序的字符串,而产生上述结果:删除所有断点后,改正源代码,运行:代码改正:将每个元素向前移一位,将原来string2【0】中的‘\0’放到最后即可。
C语言技术的调试技巧——快速定位与修复错误C语言作为一种强大且广泛应用的编程语言,常常会遇到各种各样的bug和错误。
对于程序员来说,调试是一个必不可少的技能。
本文将介绍一些C语言调试的技巧,帮助程序员们能够快速地定位和修复错误。
一、使用调试器使用调试器是调试C语言程序的最有效和常用的方法之一。
在大多数集成开发环境(IDE)中,都内置了调试器工具。
调试器可以让程序一步一步地执行,观察程序运行状态,检查变量的值和程序流程。
当程序出现错误时,可以通过调试器来查找错误的源头,并做出相应的修改。
常用的调试器有GDB(GNU调试器)和Visual Studio调试器。
二、输出调试信息在调试过程中,输出调试信息是一种非常有效的方法。
通过在程序中插入一些输出语句,可以观察程序运行到哪一步,并输出相关变量的值。
这些调试信息可以帮助程序员快速定位错误,并判断某些变量是否符合预期。
一般来说,可以使用printf函数来输出调试信息,但要注意在程序发布前删除或注释掉这些输出语句,以避免对程序性能造成负面影响。
三、利用断言断言(Assertion)是一种在程序中加入的检查语句,用于判断某个条件是否满足。
如果条件为真,程序将继续执行;如果条件为假,程序将中断执行并输出相应的错误信息。
在C语言中,可以使用assert宏来实现断言机制。
通过在关键位置添加断言语句,可以在程序运行时自动检查错误条件,提供即时的错误信息。
断言是一种非常有效的调试手段,在开发和测试阶段广泛应用。
四、逐步检查代码当程序出现错误时,逐步检查代码是一种常用的调试方法。
可以从程序的起点开始,逐行或逐块地检查代码,观察变量的变化和程序的执行流程。
通过逐步检查,可以发现代码中存在的逻辑错误、语法错误和数据错误,并及时进行修复。
这种方法特别适用于程序较小且结构清晰的情况下,但对于复杂的程序可能会比较耗时。
五、使用合适的数据结构选择合适的数据结构是提高程序可读性和可维护性的重要因素之一。
实验名称 实验三 用GDB调试程序的bug
实验时间 05 月 23 日星期 四 第 3 节
实验目的
通过调试一个有问题的程序,使读者进一步熟练使用vim操作,并且
熟练掌握gcc编译命令及gdb的调试命令,通过对有问题程序的跟踪调
试,进一步提高发现问题和解决问题的能力。
实验环境
VMware虚拟机、Linux操作系统
实验内容
(步骤、
方法、算
法、程
序)
实验内容:
使用VI编辑器,将以下代码输入到名为greet.c 的文件中。此代码的原
意为输出倒
序main函数中定义的字符串,但结果显示没有输出。代码如下所示: .
#include
int display1(char *string);
int display2(char * string);
int main (){
char string[ ] = "Embedded Linux";
display1 (string);
display2 (string);
}
int display1 (char *string)
{
printf ("The original string is %s \n", string);
}
int display2 (char * string1){
char *string2;
int size,i;
size = strlen (string1);
string2 = (char *) malloc (size + 1);
for(i=0;i
string2[size+1] =’ ’;
printf("The string afterward is %s \n",string2);
}
(2)使用Gcc编译这段代码,注意要加上“g”
选项以方便之后的调试。.
(3)运行生成的可执行文件,观察运行结果。
(4)使用Cdb调试程序,通过设置断点、
单步跟踪,一步步找出错误所在。
(5)纠正错误,更改源程序并得到正确的结果。
实验步骤:
(1)在工作目录上新建文件greet.c,并用vim进入文件进行编辑
(2)在Vi中输入以上代码。
(3)在Vi中保存并退出: wq。
(4)用Gcc编译: gcc -g greet.c -o greet
(5)运行greet: . /greet
产生此错误的原因是少了两个头文件
#include
#include
输入头文件再运行这个错误就没有了
输出为:
The original string is Embedded Limux
The string afterward is
可见,该程序没有能够倒序输出。
(6)启动Gdb调试: gdb greet
(7)查看源代码,使用命令”l”。
(8)在30行(for循环处)设置断点,使用命令”b 30"。
(9)在33行(printf函数处)设置断点,使用命”b 33。
(10)查看断点设置情况,使用命令info b”
(11)运行代码,使用命令“r”。
(12) 单步运行代码,使用命令“n”。
(13)查看暂停点变量值,使用命令”p string2[size-i]"。
(12)继续单步运行代码数次,并使用命令查看,发现string2[size-i]的
值是正确的
(15)继续程序的运行,使用命令”c”。
(16)此时依次查看sting2[0]、string2[1]. . ,发现string[0]没有被
正确赋值,而后面都是正确的,这时,定位程序第31行,发现程序运行
错误的原因在于“size-1”,由于i只能增加到size-1,这样string2[0]就
(接上)
实验内容
(步骤、
方法、算
法、程
序)
永远不能被赋值而保持NULL,故输不出任何结果。
(17)退出Gdb,使用命令q.
(18) 重新编辑greet.c把其中的“string2[size - i] = string1[i];"
改为“string2[size – i-1] = . string1[i]"即可。
(19)使用Gcc重新编译:
gcc -g greet.c -o greet
(20)查看运行结果 ./greet
The original string is Embedded Linux
The string aferward is xuniL deddedbmE
这时,输入结果正确。
部分源程序代码/实验配置 本实验部分代码 int display2 (char * string1){ char *string2; int size,i; size = strlen (string1);
string2 = (char *) malloc (size + 1);
for(i=0;i
string2[size+1] =’ ’;
printf("The string afterward is %s \n",string2);
}
实验结果
与结论
成功调试,使程序成功运行
试验心得
与小结
更加熟练掌握gcc编译命令及gdb的调试命令
指导教师
评议
成绩评定: 指导教师签名: