gdb 笔记(07)— 自动显示变量值、显示源代码、监视变量或内存、查看内存
1. 自动显示变量的值
使用 print
或者 p
命令来显示变量的值,但是有一个问题,即如果想要查看某个变量的值,需要不停地使用 print
命令。这对于需要观察那些不停变化的变量值来说,使用 p
命令就不太方便了,因为需要使用多次。
gdb
还有另外一个 display
命令,每次程序暂停都可以自动显示变量值。语法如下:
display 变量名
后面可以跟多个变量名,比如 display {var1,var2,var3}
。
我们使用 display
来自动观察 fun_test
中的变量 x
,而不是使用 print
命令,源码 demo.cpp
代码如下:
#include <iostream>
#include <string>void fun_test(int a, const char *str)
{printf("a is %d, str is %s\n", a, str);
}int main(int argc, char *argv[])
{for (int i = 0; i < 10; i++){fun_test(i, "test");}
}
调试过程如下:
(gdb) b fun_test
Breakpoint 1 at 0x799: file demo.cpp, line 6.
(gdb) r
Starting program: /home/wohu/cppProject/book_debug/chapter_3.1/demo Breakpoint 1, fun_test (a=0, str=0x5555555548e9 "test") at demo.cpp:6
6 printf("a is %d, str is %s\n", a, str);
(gdb) p a
$1 = 0
(gdb) p a
$2 = 0
(gdb) c
Continuing.
a is 0, str is testBreakpoint 1, fun_test (a=1, str=0x5555555548e9 "test") at demo.cpp:6
6 printf("a is %d, str is %s\n", a, str);
(gdb) p a
$3 = 1
(gdb) c
Continuing.
a is 1, str is testBreakpoint 1, fun_test (a=2, str=0x5555555548e9 "test") at demo.cpp:6
6 printf("a is %d, str is %s\n", a, str);
(gdb) p a
$4 = 2
(gdb) display a
1: a = 2
(gdb) c
Continuing.
a is 2, str is testBreakpoint 1, fun_test (a=3, str=0x5555555548e9 "test") at demo.cpp:6
6 printf("a is %d, str is %s\n", a, str);
1: a = 3
(gdb) c
Continuing.
a is 3, str is testBreakpoint 1, fun_test (a=4, str=0x5555555548e9 "test") at demo.cpp:6
6 printf("a is %d, str is %s\n", a, str);
1: a = 4
(gdb) c
Continuing.
a is 4, str is testBreakpoint 1, fun_test (a=5, str=0x5555555548e9 "test") at demo.cpp:6
6 printf("a is %d, str is %s\n", a, str);
1: a = 5
(gdb)
如果 display
命令后面跟多个变量名,则必须要求这些变量的类型相同(比如都是整型变量)。如果长度不相同,则需要分开使用。
可以在 gdb
中输入 info display
命令来查看已经设置的自动显示的变量信息,如图所示。
(gdb) info display
Auto-display expressions now in effect:
Num Enb Expression
1: y a (cannot be evaluated in the current context)
(gdb)
如果不需要某些变量自动显示,则可以使用 undisplay 编号
的方式来取消自动变量的显示。例如,想要取消上面变量 a
的自动显示,则可以在 gdb
里面输入 undisplay 1
命令,a
变量的自动显示被取消,如图所示。这样一来,再次使用 info display
命令的时候不会显示 a
的信息。
(gdb) undisplay 1
(gdb) info display
There are no auto-display expressions now.
(gdb)
如果要取消所有变量的自动显示,可以使用 undisplay
命令来。在使用 undisplay
命令时会收到确认信息,确认是否全部取消自动显示。如果输入 y
,则取消所有的自动显示。delete display
命令也可以删除所有的自动显示。如果只想删除部分变量的自动显示,可以使用 delete display 序号
的方式。
比如要删除中的{x,a}的自动显示,则输入以下命令:
delete display 1
除了删除自动显示,还可以暂时禁用自动显示,在需要的时候可以再次启用某些变量的自动显示。比如图3-64中自动显示的编号 1 和 2,如果要暂时禁用编号为 1 的自动显示,则可以使用以下命令:
disable display 1
如果想要恢复编号为1的变量的自动显示,则可以使用以下命令来恢复:
enable display 1
2. 显示源代码
gdb
可以在调试的时候显示源代码信息。查看源代码的命令是 list
或者 l
。当程序命中断点或者暂停后可以使用 list
命令查看相关的源代码。
因为加上编译选项 -g
后,生成的可执行文件中包含调试信息,并且保存了对应的源文件信息(只是保存了源文件名等信息),所以在查看源代码时,要确保对应的源文件存在,否则无法查看。
在程序中断时,可以使用 l
命令来查看源代码信息。默认情况下,使用 l
命令可以显示10行源代码—当前代码行的前面 5 行和后面 5 行,
(gdb) c
Continuing.Breakpoint 1, fun_test (a=7, str=0x5555555548e9 "test") at demo.cpp:6
6 printf("a is %d, str is %s\n", a, str);
(gdb) l
1 #include <iostream>
2 #include <string>
3
4 void fun_test(int a, const char *str)
5 {6 printf("a is %d, str is %s\n", a, str);
7 }
8
9 int main(int argc, char *argv[])
10 {(gdb)
继续执行 l
命令,则会继续从当前行往后显示10行代码。如果执行 l-
命令,则会从当前代码行往前显示10行代码,
(gdb) l
11 for (int i = 0; i < 10; i++)
12 {13 fun_test(i, "test");
14 }
15 }
(gdb)
执行 l
命令时,每次默认显示 10 行代码,如果觉得每次显示的代码太少,可以通过 set listsize
命令来改变每次显示代码的行数。比如,希望每次能够显示 20 行代码,可执行下述命令:
set listsize 20
这样,每次调用 list
命令时,就会显示 20 行代码。
还可以使用 list
命令查看指定函数的代码,语法为 list 函数名
。比如,我们要查看 fun_test
函数的源代码,可以使用下述命令:
list fun_test
显示函数与显示普通代码的规则相同。
- 受到行数的限制,比如我们刚设置了每次显示20行代码,则显示
fun_test
函数时只显示20行代码; - 仍然会以上下文的方式显示函数代码,即显示函数前面 10 行代码和函数后面 10 行代码;
(gdb) l fun_test
1 #include <iostream>
2 #include <string>
3
4 void fun_test(int a, const char *str)
5 {6 printf("a is %d, str is %s\n", a, str);
7 }
8
9 int main(int argc, char *argv[])
10 {(gdb)
如果想要查看指定文件的指定行代码,则可以使用下述命令:
list 文件名:行号
如果查看的是当前文件的代码行,则可以省略文件名。比如我们要查看 demo.cpp
的第 100 行代码,则可以使用下述命令进行查看:
l 100
示例过程
(gdb) l demo.cpp:9
4 void fun_test(int a, const char *str)
5 {6 printf("a is %d, str is %s\n", a, str);
7 }
8
9 int main(int argc, char *argv[])
10 {11 for (int i = 0; i < 10; i++)
12 {13 fun_test(i, "test");
(gdb) l 13
8
9 int main(int argc, char *argv[])
10 {11 for (int i = 0; i < 10; i++)
12 {13 fun_test(i, "test");
14 }
15 }
(gdb)
3. watch
watch
可以用来监视一个变量或者一段内存,当这个变量或者该内存处的值发生变化时,GDB
就会中断下来。被监视的某个变量或者某个内存地址会产生一个 watch point
(观察点)。
适用场景:
有一个变量其值被意外地改掉了,通过单步调试或者挨个检查使用该变量的代码工作量会非常大,如何快速地定位到该变量在哪里被修改了?其实使用 watch
命令就可以通过添加硬件断点来达到监视数据变化的目的。
watch
命令的使用方式是 watch 变量名或内存地址
,一般有以下几种形式:
- 形式一:整型变量
int i;
watch i
- 形式二:指针类型
char *p;
watch p 与 watch *p
注意:watch p
与 watch *p
是有区别的,前者是查看 *(&p)
,是 p
变量本身;后者是 p
所指内存的内容。我们需要查看地址,因为目的是要看某内存地址上的数据是怎样变化的。
- 形式三:
watch
一个数组或内存区间
char buf[128];
watch buf
这里是对 buf
的 128 个数据进行了监视,此时不是采用硬件断点,而是用软中断实现的。用软中断方式去检查内存变量是比较耗费 CPU
资源的,精确地指明地址是硬件中断。
注意:当设置的观察点是一个局部变量时,局部变量无效后,观察点也会失效。在观察点失效时 GDB
可能会提示如下信息:
Watchpoint 2 deleted because the program has left the block in which its expression is valid.
4. 查看内存
test_memory
函数内容
定义了字符串类型、int 变量和一个结构体,使用 gdb
启动调试,执行 b test_memory
命令为test_memory
函数设置一个断点,或者直接在 124 行设置一个断点。断点命中时,使用 x
命令查看各个变量的内存信息。x
命令的语法如下:
x /选项 地址
先查看字符串变量 str
的内存信息。执行 x str
,默认以十六进制显示。由于 str
是字符串,所以也可以使用字符串的方式查看。使用命令 x /s str
还可以以十进制方式查看、设定显示的宽度等,如图所示。
以十六进制方式查看时,显示的内存内容为0x74736574,对应的字符分别为t、s、e、t,即在内存中存储的内容刚好与我们看到的情况相反。如果以 x /s str
的方式查看,则会直接显示字符串的内容。
再来查看 int
型变量 number
在内存中的信息。因为 number
不是一个指针,所以我们要首先找到它的地址。可以使用 p &number
命令来查看 number
对应的地址,然后再使用 x
来查看 number
地址对应的内存数据。当然也可以直接使用 x &number
的方式来查看 number
地址对应的内存信息,如图所示。
在代码中,我们为 number
赋值为 0x12345678
,但是内存中显示的却是 0x78563412
,原因是字节在x86
架构中是按照小端方式存储的,第2章中已经介绍过。小端存储是指字节序数据的尾端数据存放在低地址部分,所以与我们看到的顺序刚好相反。
变量node存储的数据是一个结构体类型。来看看node在内存中到底是如何存储的。在gdb中输入命令x/16s node,如图3-73所示。
从图中可以看到,node在内存中的存储顺序与结构体中声明成员的顺序一致,即按照性别、ID和姓名来存储。显示性别的起始地址是0x614e70,显示ID的起始地址是0x614e74,“d”对应的是十进制的100。可以发现,ID的起始地址和性别的起始地址相差4,但是我们定义gender成员时使用的是char gender[3],明明只声明了3字节,最后却在内存中占用了4字节。
这是因为结构体在内存中会进行对齐和补齐操作,默认是按照4字节对齐。尽管声明的是3字节,但是要按照4字节去对齐,所以需要补齐1字节,这导致gender占用了4字节空间。同样,成员Name也会补齐到8字节,所以整个结构体在内存中会占用16字节,可以使用p sizeof(TEST_NODE)命令进行查看。在图3-73中也可以发现,整个结构体的大小是16字节。
命令x并不局限于查看变量的内存信息,无论是函数地址、变量地址,还是其他地址,只要地址合法而且可以访问,都可以使用 x 命令来查看。
gdb 笔记(07)— 自动显示变量值、显示源代码、监视变量或内存、查看内存相关推荐
- 基于STM32的0.96OLED基本显示学习,及 上下或左右的滑动显示长字符(使用硬件刷屏模式),OLED显示变量值操作详细解析
基于STM32的0.96OLED基本显示学习,及 上下或左右的滑动显示长字符(使用硬件刷屏模式),OLED显示变量值操作详细解析 简 介 一.项目说明 二.学习入门 1)开始了解例程 三.实战过程 ...
- python显示变量值_Python 中如何打印变量值
展开全部 python打印变量的值需32313133353236313431303231363533e78988e69d8331333366306435要用到print语句,具体的使用方法如下: 1. ...
- 竖排显示变横排显示的方法
以上是VC的属性页,怎么设计使得竖排显示变成横排显示啊??? 感觉这两个界面不是一样的,不能这样的问,所以本问题取消.
- 《JavaScript高级程序设计(第四版)》红宝书学习笔记(2)(第四章:变量、作用域与内存)
个人对第四版红宝书的学习笔记.不适合小白阅读.这是part2.持续更新,其他章节笔记看我主页. (记 * 的表示是ES6新增的知识点,记 ` 表示包含新知识点) 第四章:变量.作用域与内存 4.1 原 ...
- jsp当前页的变量值显示到文本框中hint_Word中常用的这9个打印技巧,你不一定全懂,非常实用...
在工作中,经常需要打印各种文档,看似很简单的操作,如果使用不当,也是很麻烦的事儿,不要说浪费纸张,还有可能打印不出你想要的结果. 今天,我们就来分享一下word2016中的9个实用打印技巧,一定能帮到 ...
- java中label数值_java – 如何在JLabel中显示变量值
我是 Java编程的新手.我想在输出窗口中显示我的变量的值,而不是在控制台视图中. 代码如下: import java.awt.BorderLayout; import javax.swing.JFr ...
- ECLIPSE 调试模式无法显示 变量值
网上搜索了一下,方法集中在两种: 1. Window->Preferences->Java->Editor->Hovers 将[Variable Values]选择即可,如果 ...
- mysql 存储过程 用户变量值_mysql:用户变量、系统变量、局部变量(存储过程中的)...
MySQL数据库中的变量分为MySQL系统变量和MySQL用户变量. 一.MySQL用户变量:基于会话变量实现的, 可以暂存值, 并传递给同一连接里的下一条sql使用的变量.当客户端连接退出时,变量会 ...
- IAR中如何实时观察变量值
用一个简单的程序演示一下,首先进入到调试界面. 选中要观察的变量,然后单击鼠标右键选择 Add to Watch "j",将要观察的变量依次添加到观察窗口,然后单步执行,或者让程序 ...
最新文章
- poj3096(set的应用)
- R语言使用ggplot2包使用geom_violin函数绘制分组小提琴图(自定义分组的次序)实战
- 李茶:虎牙直播推荐系统架构详解
- 社交网络图挖掘1--将社交网络看作图及其聚类
- js中!和!!的区别及用法
- MFC类结构-1、CObject类
- 一个比较简单驱动程序初学者可以看看
- 小白学数据分析-----ARPDAU的价值
- C++读写文件总结 .
- 华为机试HJ23:删除字符串中出现次数最少的字符
- iOS开发之网络编程--使用NSURLConnection实现大文件断点续传下载+使用输出流代替文件句柄...
- Windows XP Embedded下载
- 三维空间坐标的旋转算法详解_任意旋转角三维空间直角坐标转换的迭代算法
- 如何利用eclipse创建一个java web项目?
- HackTheBox - Unified
- 13-TCP 协议(FIN_WAIT2)
- npm查看一个包的版本信息
- python计算机视觉学习第三章——图像到图像的映射
- uber优步提高成单率,轻松拿奖励!
- 发光二极管的keil代码c语言,用Keil点亮一个发光二极管
热门文章
- java开发 Ultraedit_Java开发工具配置 UltraEdit
- matlab最小二乘 弹性网络,基于弹性SCAD罚函数的回声状态网络时间序列预测方法与流程...
- class path resource [spring/] cannot be resolved to URL because it does not exist问题解决(IDEA)
- 使用OpenXml转换docx内容为RTF
- angular :ngIf 的else用法
- 【PaperReading】OpenHGNN:An Open-Source Toolkit for Heterogeneous Graph Neural Networks
- 大专出身,28K上岸B站测开岗,光一面就花了我8个小时···
- 计算机存储器的种类有哪些,计算机存储器的种类和特点
- 渗透测试完整流程(未完待续)
- java 使用fusioncharts_FusionCharts使用教程:自定义图表——画布