【Linux系统编程】代码调试工具gdb--2

简介: 【Linux系统编程】代码调试工具gdb--2

【Linux系统编程】代码调试工具gdb--1 https://developer.aliyun.com/article/1424715

 当设置完断点后可使用 info b 指令查看我们设置的所有断点。具体的解释如下:


//使用b n 在第n行设置断点,设置完之后可观察到断点的地址、文件的来源和设置的行数
(gdb) b 5     
Breakpoint 1 at 0x4007e5: file code.cpp, line 5.     
(gdb) b 8
Breakpoint 2 at 0x4007f5: file code.cpp, line 8.
(gdb) b 11
Breakpoint 3 at 0x40081d: file code.cpp, line 11.
(gdb) info b
//显示所有有关断点的信息
/*Num表示断点的编号。Type表示设置类型,这里是断点。 Enb表示断点的功能的开闭,y是yes的意思,表示断点的功能正常,n是no的意思,表示断点的功能关闭,但断点还存在。Address表示断点的地址。What表示断点在哪个函数、哪个文件、哪一行中。*/
Num     Type           Disp Enb Address            What
1       breakpoint     keep y   0x00000000004007e5 in main() at code.cpp:5
2       breakpoint     keep y   0x00000000004007f5 in main() at code.cpp:8
3       breakpoint     keep y   0x000000000040081d in main() at code.cpp:11


       delete(简写:d)是删除断点的指令。使用方法:d n 删除编号为n的断点。注意,这里的n代表编号,不是行数。这里可使用info b指令查看Num中的标号。


(gdb) info b
Num     Type           Disp Enb Address            What
1       breakpoint     keep y   0x00000000004007e5 in main() at code.cpp:5
2       breakpoint     keep y   0x00000000004007f5 in main() at code.cpp:8
3       breakpoint     keep y   0x000000000040081d in main() at code.cpp:11
(gdb) d 1       //删除编号1的断点
(gdb) info b
Num     Type           Disp Enb Address            What
2       breakpoint     keep y   0x00000000004007f5 in main() at code.cpp:8
3       breakpoint     keep y   0x000000000040081d in main() at code.cpp:11
(gdb) d 2       //删除编号2的断点
(gdb) info b
Num     Type           Disp Enb Address            What
3       breakpoint     keep y   0x000000000040081d in main() at code.cpp:11
(gdb) d 3        //删除编号3的断点
(gdb) info b
No breakpoints or watchpoints.    //显示断点已删除完毕

 


       当我们设置完断点时,默认断点的功能是打开的。当我们使用 disable n(这里的n表示断点的编号) 指令时,可将编号为n的断点功能失效,但不删除。当使用 enable n(这里的n表示断点的编号) 指令时,可将编号为n的断点功能打开,与disable功能相反。


       这里要说明的是,使用disable/enable后,由于调试断点的设置已被更改,当使用 r(run) 运行程序时,系统可能会提醒是否重新生成程序运行。


(gdb) info b
Num     Type           Disp Enb Address            What
1       breakpoint     keep y   0x00000000004007e5 in main() at code.cpp:5
2       breakpoint     keep y   0x00000000004007f5 in main() at code.cpp:8
3       breakpoint     keep y   0x000000000040081d in main() at code.cpp:11
(gdb) disable 2
(gdb) info b
Num     Type           Disp Enb Address            What
1       breakpoint     keep y   0x00000000004007e5 in main() at code.cpp:5
2       breakpoint     keep n   0x00000000004007f5 in main() at code.cpp:8
3       breakpoint     keep y   0x000000000040081d in main() at code.cpp:11
(gdb) enable 2
(gdb) info b
Num     Type           Disp Enb Address            What
1       breakpoint     keep y   0x00000000004007e5 in main() at code.cpp:5
2       breakpoint     keep y   0x00000000004007f5 in main() at code.cpp:8
3       breakpoint     keep y   0x000000000040081d in main() at code.cpp:11

逐过程和逐语句:


       逐语句是一行一行进行分析,它将会进入函数内部。逐过程是一次直接执行一个过程,它将一次直接执行完一个函数,不会进行函数内部分析。


       在gdb调试中,逐过程的指令是next,简写:n。逐语句的指令是step,简写:s。当在使用一次逐过程/逐语句后,下面直接按 “回车” 键即可继续往下面运行,也可不断使用n/s往下面运行,而在此过程中,我们可使用 p [变量](print的简写) 查看变量的内容,如:p n 查看数据中n的值,p &s 查看变量s的地址。这里需注意,p指令使用无法一直显示数据,当再次进行操作时,变量的内容将会消失。display [变量] 将会永久的显示数据。undisplay n(这里的n代表编号) 将会把编号为n的显示内容删除。


(gdb) info b
Num     Type           Disp Enb Address            What
1       breakpoint     keep y   0x00000000004007f3 in main() at code.cpp:6
2       breakpoint     keep y   0x0000000000400839 in main() at code.cpp:13
3       breakpoint     keep y   0x00000000004008fd in main() at code.cpp:20
4       breakpoint     keep y   0x0000000000400a15 in main() at code.cpp:30
(gdb) r
.........
(gdb) n   //逐过程分析
8            cout << "兔子" << endl;
(gdb)    //回车继续运行
兔子
main () at code.cpp:9
9            i++;
.........
//使用p指令显示一次数据的内容
(gdb) p i   
$1 = 5
(gdb) p n
$2 = 10
(gdb) p &i
$3 = (int *) 0x7fffffffe4dc
//可发现p指令不能永久显示
(gdb) n
8            cout << "兔子" << endl;
//使用display指令永久显示数据内容
(gdb) display i
1: i = 6    //i变量编号1
(gdb) display n
2: n = 10  //n变量编号2
//逐过程继续运行还会看到数据内容
(gdb) n
兔子
9            i++;
2: n = 10
1: i = 6
//使用undisplay指令删除指定数据内容,注意,这里要输入编号
(gdb) undisplay n   //输入变量,出现错误
warning: bad display number at or near 'n'
(gdb) undisplay 2  //输入编号2,删除编号2变量的内容
(gdb) n
8            cout << "兔子" << endl;
1: i = 8

范围式查找:


       范围式调试常用指令有以下:


           continue(简写:c):从一个断点运行到下一个断点或程序结束。它通常用来范围查找。


           bt:查看当前函数的堆栈信息,根据函数栈帧发现问题。


           finish:运行当前所在的函数,将当前所在的一个函数运行结束后就停止。但是,它不会            将主函数一次运行完。


           until n(n代表行号):直接将程序运行到第n行,若中间出现死循环,在运行中将会出现死            循环问题。


       以上几个指令都是在源代码基础上进行局部分析,但在调试中,我们可能会想测试源代码中某些变量改变后的情况。通常,使用 set var [改变内容] 指令即可完成。如:set var flag=0 查看将源代码中变量flag的值变为0时的测试情况。


注意:


       1,使用set var指令改变内容时,要改变的变量必须已经在内部存储过,即程序已经运行到这部分时才可改变。


       2,set var改变内容只是在测试中改变,不会影响源代码的内容,在测试时可放心使用。


(gdb) info b
Num     Type           Disp Enb Address            What
1       breakpoint     keep y   0x00000000004007f3 in main() at code.cpp:6
2       breakpoint     keep y   0x0000000000400855 in main() at code.cpp:14
3       breakpoint     keep y   0x00000000004008fd in main() at code.cpp:20
4       breakpoint     keep y   0x0000000000400a15 in main() at code.cpp:30
(gdb) r       //run的简写,直接运行到编号1断点的位置
.............
(gdb) c      //continue的简写,从当前断点位置运行到编号2断点的位置
.............
(gdb) bt
#0  main () at code.cpp:14   //主函数栈帧
(gdb) until 18    //将程序从当前位置直接运行到第18行
.............
(gdb) set var i=6    //改变变量i的值
(gdb) p i    //查看i已经改变过
$1 = 6
(gdb) finish   //直接运行完一个函数(方法),这里程序在主函数中,因此不能正常运行
"finish" not meaningful in the outermost frame.


相关实践学习
阿里云图数据库GDB入门与应用
图数据库(Graph Database,简称GDB)是一种支持Property Graph图模型、用于处理高度连接数据查询与存储的实时、可靠的在线数据库服务。它支持Apache TinkerPop Gremlin查询语言,可以帮您快速构建基于高度连接的数据集的应用程序。GDB非常适合社交网络、欺诈检测、推荐引擎、实时图谱、网络/IT运营这类高度互连数据集的场景。 GDB由阿里云自主研发,具备如下优势: 标准图查询语言:支持属性图,高度兼容Gremlin图查询语言。 高度优化的自研引擎:高度优化的自研图计算层和存储层,云盘多副本保障数据超高可靠,支持ACID事务。 服务高可用:支持高可用实例,节点故障迅速转移,保障业务连续性。 易运维:提供备份恢复、自动升级、监控告警、故障切换等丰富的运维功能,大幅降低运维成本。 产品主页:https://www.aliyun.com/product/gdb
相关文章
|
NoSQL Linux 编译器
GDB符号表概念和在Linux下获取符号表的方法
通过掌握这些关于GDB符号表的知识,你可以更好地管理和理解你的程序,希望这些知识可以帮助你更有效地进行调试工作。
582 16
|
安全 算法 Ubuntu
Linux(openssl)环境:编程控制让证书自签的技巧。
总结:在Linux环境中,OpenSSL是一个非常实用的工具,可以帮助我们轻松地生成自签名证书。通过上述三个简单步骤,即可为内部网络、测试环境或开发环境创建自签名证书。但在公共访问场景下,建议购买经过权威认证机构签发的证书,以避免安全警告。
713 13
|
NoSQL Linux 开发工具
Linux环境基础开发工具的使用(yum、vim、gcc、g++、gdb、make/Makefile)
本文介绍了yum 包管理工具、Vim 编辑器、gcc/g++ 编译器、gdb 调试器、编译原理及 Makefile 的使用,同时还配备了如何使用,以及图解。旨在帮助读者更好地理解和应用这些工具与技术。
623 0
|
Linux
Linux编程: 在业务线程中注册和处理Linux信号
通过本文,您可以了解如何在业务线程中注册和处理Linux信号。正确处理信号可以提高程序的健壮性和稳定性。希望这些内容能帮助您更好地理解和应用Linux信号处理机制。
325 26
|
JavaScript Ubuntu Linux
如何在阿里云的linux上搭建Node.js编程环境?
本指南介绍如何在阿里云Linux服务器(Ubuntu/CentOS)上搭建Node.js环境,包含两种安装方式:包管理器快速安装和NVM多版本管理。同时覆盖全局npm工具配置、应用部署示例(如Express服务)、PM2持久化运行、阿里云安全组设置及外部访问验证等步骤,助你完成开发与生产环境的搭建。
|
Linux
Linux编程: 在业务线程中注册和处理Linux信号
本文详细介绍了如何在Linux中通过在业务线程中注册和处理信号。我们讨论了信号的基本概念,并通过完整的代码示例展示了在业务线程中注册和处理信号的方法。通过正确地使用信号处理机制,可以提高程序的健壮性和响应能力。希望本文能帮助您更好地理解和应用Linux信号处理,提高开发效率和代码质量。
346 17
|
存储 监控 Linux
嵌入式Linux系统编程 — 5.3 times、clock函数获取进程时间
在嵌入式Linux系统编程中,`times`和 `clock`函数是获取进程时间的两个重要工具。`times`函数提供了更详细的进程和子进程时间信息,而 `clock`函数则提供了更简单的处理器时间获取方法。根据具体需求选择合适的函数,可以更有效地进行性能分析和资源管理。通过本文的介绍,希望能帮助您更好地理解和使用这两个函数,提高嵌入式系统编程的效率和效果。
797 13
|
NoSQL 编译器 C语言
C语言调试是开发中的重要技能,涵盖基本技巧如打印输出、断点调试和单步执行,以及使用GCC、GDB、Visual Studio和Eclipse CDT等工具。
C语言调试是开发中的重要技能,涵盖基本技巧如打印输出、断点调试和单步执行,以及使用GCC、GDB、Visual Studio和Eclipse CDT等工具。高级技巧包括内存检查、性能分析和符号调试。通过实践案例学习如何有效定位和解决问题,同时注意保持耐心、合理利用工具、记录过程并避免过度调试,以提高编程能力和开发效率。
678 1
|
NoSQL Linux C语言
Linux GDB 调试
Linux GDB 调试
359 10
|
NoSQL Linux C语言
嵌入式GDB调试Linux C程序或交叉编译(开发板)
【8月更文挑战第24天】本文档介绍了如何在嵌入式环境下使用GDB调试Linux C程序及进行交叉编译。调试步骤包括:编译程序时加入`-g`选项以生成调试信息;启动GDB并加载程序;设置断点;运行程序至断点;单步执行代码;查看变量值;继续执行或退出GDB。对于交叉编译,需安装对应架构的交叉编译工具链,配置编译环境,使用工具链编译程序,并将程序传输到开发板进行调试。过程中可能遇到工具链不匹配等问题,需针对性解决。
1238 3