前言

在启动调试以及设置断点之后,就到了我们非常关键的一步-查看变量。GDB调试最大的目的之一就是走查代码,查看运行结果是否符合预期。既然如此,我们就不得不了解一些查看各种类型变量的方法,以帮助我们进一步定位问题。

准备工作

在查看变量之前,需要先启动调试并设置断点,该部分内容可参考《GDB调试指南-启动调试》和《GDB调试指南-断点设置》。后面的内容都基于在某个位置已经断住。

本文辅助说明程序如下:
testGdb.c

//testGdb.c
#include<stdio.h>
#include<stdlib.h>
#include"testGdb.h"
int main(void)
{
    int a = 10; //整型
    int b[] = {1,2,3,5};  //数组
    char c[] = "hello,shouwang";//字符数组
    /*申请内存,失败时退出*/    
    int *d = (int*)malloc(a*sizeof(int));
    if(NULL == d)
    {
        printf("malloc error\n");
        return -1;
    }
    /*赋值*/
    for(int i=0; i < 10;i++)
    {
        d[i] = i;
    }
    free(d);
    d = NULL;
    float e = 8.5f;
    return 0;
}

testGdb.h

int a = 11;

编译:

$ gcc -g -o testGdb testGdb.o

变量查看

打印基本类型变量,数组,字符数组

最常见的使用便是使用print(可简写为p)打印变量内容。
例如,打印基本类型,数组,字符数组等直接使用p 变量名即可:

(gdb) p a
$1 = 10
(gdb) p b
$2 = {1, 2, 3, 5}
(gdb) p c
$3 = "hello,shouwang"
(gdb) 

当然有时候,多个函数或者多个文件会有同一个变量名,这个时候可以在前面加上文件名或者函数名来区分:

(gdb) p 'testGdb.h'::a
$1 = 11
(gdb) p 'main'::b
$2 = {1, 2, 3, 5}
(gdb) 

这里所打印的a值是我们定义在testGdb.h文件里的,而b值是main函数中的b。

打印指针指向内容

如果还是使用上面的方式打印指针指向的内容,那么打印出来的只是指针地址而已,例如:

(gdb) p d
$1 = (int *) 0x602010
(gdb) 

而如果想要打印指针指向的内容,需要解引用:

(gdb) p *d
$2 = 0
(gdb) p *d@10
$3 = {0, 1, 2, 3, 4, 5, 6, 7, 8, 9}
(gdb) 

从上面可以看到,仅仅使用*只能打印第一个值,如果要打印多个值,后面跟上@并加上要打印的长度。
或者@后面跟上变量值:

(gdb) p *d@a
$2 = {0, 1, 2, 3, 4, 5, 6, 7, 8, 9}
(gdb) 

由于a的值为10,并且是作为整型指针数据长度,因此后面可以直接跟着a,也可以打印出所有内容。

另外值得一提的是,$可表示上一个变量,而假设此时有一个链表linkNode,它有next成员代表下一个节点,则可使用下面方式不断打印链表内容:

(gdb) p *linkNode
(这里显示linkNode节点内容)
(gdb) p *$.next
(这里显示linkNode节点下一个节点的内容)

如果想要查看前面数组的内容,你可以将下标一个一个累加,还可以定义一个类似UNIX环境变量,例如:

(gdb) set $index=0
(gdb) p b[$index++]
$11 = 1
(gdb) p b[$index++]
$12 = 2
(gdb) p b[$index++]
$13 = 3

这样就不需要每次修改下标去打印啦。

按照特定格式打印变量

对于简单的数据,print默认的打印方式已经足够了,它会根据变量类型的格式打印出来,但是有时候这还不够,我们需要更多的格式控制。常见格式控制字符如下:

  • x 按十六进制格式显示变量。
  • d 按十进制格式显示变量。
  • u 按十六进制格式显示无符号整型。
  • o 按八进制格式显示变量。
  • t 按二进制格式显示变量。
  • a 按十六进制格式显示变量。
  • c 按字符格式显示变量。
  • f 按浮点数格式显示变量。

还是以辅助程序来说明,正常方式打印字符数组c:

(gdb) p c
$18 = "hello,shouwang"

但是如果我们要查看它的十六进制格式打印呢?

(gdb) p/x c
$19 = {0x68, 0x65, 0x6c, 0x6c, 0x6f, 0x2c, 0x73, 0x68, 0x6f, 0x75, 0x77, 0x61, 
  0x6e, 0x67, 0x0}
(gdb)

但是如果我们想用这种方式查看浮点数的二进制格式是怎样的是不行的,因为直接打印它首先会被转换成整型,因此最终会得到8:

(gdb) p e
$1 = 8.5
(gdb) p/t e
$2 = 1000
(gdb) 

那么就需要另外一种查看方式了。

查看内存内容

examine(简写为x)可以用来查看内存地址中的值。语法如下:

x/[n][f][u] addr

其中:

  • n 表示要显示的内存单元数,默认值为1
  • f 表示要打印的格式,前面已经提到了格式控制字符
  • u 要打印的单元长度
  • addr 内存地址

单元类型常见有如下:

  • b 字节
  • h 半字,即双字节
  • w 字,即四字节
  • g 八字节

我们通过一个实例来看,假如我们要把float变量e按照二进制方式打印,并且打印单位是一字节:

(gdb) x/4tb &e
0x7fffffffdbd4:    00000000    00000000    00001000    01000001
(gdb) 

可以看到,变量e的四个字节都以二进制的方式打印出来了。

自动显示变量内容

假设我们希望程序断住时,就显示某个变量的值,可以使用display命令。

(gdb) display e
1: e = 8.5

那么每次程序断住时,就会打印e的值。要查看哪些变量被设置了display,可以使用:

(gdb)info display
Auto-display expressions now in effect:
Num Enb Expression
1:   y  b
2:   y  e

如果想要清除可以使用

delete display num #num为前面变量前的编号,不带num时清除所有。

或者去使能:

disable display num  #num为前面变量前的编号,不带num时去使能所有

微信公众号【编程珠玑】:专注但不限于分享计算机编程基础,Linux,C语言,C++,算法,数据库等编程相关[原创]技术文章,号内包含大量经典电子书和视频学习资源。欢迎一起交流学习,一起修炼计算机“内功”,知其然,更知其所以然。

公众号编程珠玑

查看寄存器内容

(gdb)info registers
rax            0x0    0
rbx            0x0    0
rcx            0x7ffff7dd1b00    140737351850752
rdx            0x0    0
rsi            0x7ffff7dd1b30    140737351850800
rdi            0xffffffff    4294967295
rbp            0x7fffffffdc10    0x7fffffffdc10
(内容过多未显示完全)

总结

通过不同方式查看变量值或者内存值能够极大的帮助我们判断程序的运行是否符合我们的预期,如果发现观察的值不是我们预期的时候,就需要检查我们的代码了。

GDB调试指南-变量查看的更多相关文章

  1. [原创]GDB调试指南-断点设置

    前言 上篇<GDB调试指南-启动调试>我们讲到了GDB启动调试的多种方式,分别应用于多种场景.今天我们来介绍一下断点设置的多种方式. 为何要设置断点 在介绍之前,我们首先需要了解,为什么需 ...

  2. GDB调试指南-单步调试

    前言 前面通过<启动调试>,<断点设置>,<变量查看>,我们已经了解了GDB基本的启动,设置断点,查看变量等,如果这些内容你还不知道,建议先回顾一下前面的内容.在启 ...

  3. GDB 调试指南

    本文首发于我的公众号 Linux云计算网络(id: cloud_dev),专注于干货分享,号内有 10T 书籍和视频资源,后台回复 「1024」 即可领取,欢迎大家关注,二维码文末可以扫. 00 介绍 ...

  4. GDB调试指南-启动调试

    前言 GDB(GNU Debugger)是UNIX及UNIX-like下的强大调试工具,可以调试ada, c, c++, asm, minimal, d, fortran, objective-c, ...

  5. roslaunch & gdb 调试指南(待补充)

    1. 安装xterm sudo apt-get install xterm 2. 在launch文件中添加如下内容: <node name="navigation" pkg= ...

  6. 一文入门Linux下gdb调试(一)

    作者:良知犹存 转载授权以及围观:欢迎添加微信号:Conscience_Remains 总述 在window下我们习惯了IDE的各种调试按钮,说实话确实挺方便的,但到了Linux下,没有那么多的IDE ...

  7. 经典的GDB调试命令,包括查看变量,查看内存

    经典的GDB调试命令,包括查看变量,查看内存 在你调试程序时,当程序被停住时,你可以使用print命令(简写命令为p),或是同义命令inspect来查看当前程序的运行数据.print命令的格式是: p ...

  8. gdb 调试入门,大牛写的高质量指南

    引用自:http://blog.jobbole.com/107759/ gdb 调试 ncurses 全过程: 发现网上的“gdb 示例”只有命令而没有对应的输出,我有点不满意.gdb 是 GNU 调 ...

  9. gdb 调试(查看运行时数据) 四

    在使用GDB调试程序时,触发断点后,可以使用print命令(简写为p),或是同义命令inspect来查看当前程序的运行数据.print命令的格式是: print <expr>    pri ...

随机推荐

  1. UML第二次作业

    一.plant UML语法学习小结 1.类之间的关系 使用.. 来代替 -- 可以得到点 线. 在这些规则下,也可以绘制下列图形 @startumlClass01 <|-- Class02 Cl ...

  2. idapython import 'site' failed

    打开IDA出现这个错误提示,问题根源是IDA找不到python,安装2.7版本的python并设置%PYTHONHOME%变量为python安装目录就可以了 如果已经安装了python可以在命令行下用 ...

  3. Android开发:文本控件详解——TextView(一)基本属性

    一.简单实例: 新建的Android项目初始自带的Hello World!其实就是一个TextView. 在activity_main.xml中可以新建TextView,从左侧组件里拖拽到右侧预览界面 ...

  4. MacBook PyCharm激活码(附视频)

    Windows激活请看这里:pyCharm最新2019激活码 此教程实时更新,请放心使用:如果有新版本出现猪哥都会第一时间尝试激活: pycharm官网下载地址:http://www.jetbrain ...

  5. 从零开始学习PYTHON3讲义(十)自己做一个“电子记事本”

    <从零开始PYTHON3>第十讲 截至上一讲,我们已经完成了Python语言的基本部分.我们用了三讲来讨论Python语言的控制结构,用了两讲来介绍Python的基本数据类型.可以说仅就语 ...

  6. @vue-cli3创建项目报错:ERROR command failed: npm install --loglevel error --registry=https://registry.npm.taobao.org --di

    使用@vue-cli3时 在你感觉所以配置都搞好开始创建项目时,不停的报错,就是创建不成功 清npm缓存也不行 改淘宝镜像也不行 就快奔溃了,最后最终(其实我在凑150字,为了能发到首页给更多采坑的兄 ...

  7. SpringBoot + Spring Security 学习笔记(一)自定义基本使用及个性化登录配置

    官方文档参考,5.1.2 中文参考文档,4.1 中文参考文档,4.1 官方文档中文翻译与源码解读 SpringSecurity 核心功能: 认证(你是谁) 授权(你能干什么) 攻击防护(防止伪造身份) ...

  8. 痞子衡嵌入式:极易上手的可视化wxPython GUI构建工具(wxFormBuilder)

    大家好,我是痞子衡,是正经搞技术的痞子.今天痞子衡给大家介绍的是wxPython GUI构建工具wxFormBuilder. 一.手工代码布局GUI界面的烦恼 如果你曾经设计过上位机软件GUI界面,初 ...

  9. 痞子衡嵌入式:串口调试工具Jays-PyCOM诞生记 - 索引

    大家好,我是痞子衡,是正经搞技术的痞子.本系列痞子衡给大家介绍的是串口调试工具Jays-PyCOM诞生. 串口调试助手是嵌入式开发里非常常用的小工具,市面上有非常多流行的串口调试工具,比如TeraTe ...

  10. [Linux] 一个前端必会的 Nginx 免费教程-在虚拟机中用deepin测试

    原文技术胖的 nginx 技术胖 专注于前端开发 deepin Linux Deepin 是一个基于 DEB 包管理的一个独立操作系统,和那些 Ubuntu(下个大版本是基于 debian 开发) 的 ...