点击蓝字,关注我们

01

概念

GDB是一个由GNU开源组织发布的、UNIX/LINUX操作系统下的、基于命令行的、功能强大的程序调试工具。

在实际应用中,有两种调试方法:在线调试和离线调试。

离线调试适用于开发测试环境,可以自由启停进程,设置断点;在线调试一般用于现场问题分析,不能随便启停进程,对于技术要求较高。

02

前提条件

    2.1 编译

若想执行gdb调试,在Makefile文件中需要增加编译调试选项-g,例如:

gdb dup_file.c –o dum_file_elf –g –lpthread

说明:-g选项的作用是在可执行文件(ELF)中加入源代码的相关信息,比如ELF中第几条机器指令对应源代码的行数。但不是把整个源文件嵌入到可执行文件中,所以在调试时必须保证gdb能找到源文件。

-g完整格式是-glevel,其中,level中指定了调试信息中包含了调试信息的多少,默认的是2,level=1最少,level=3最多。

    2.2 readelf查看段信息

例如:

readelf -S helloWorld|grep debug

注:helloWorld为文件名,如果没有任何debug信息,则不能被调试。

    2.3 file查看strip状况

下面的情况也是不可调试的:

file helloWorld

helloWorld: (省略前面内容) stripped

注:如果最后是stripped,则说明该文件的符号表信息和调试信息已被去除,不能使用gdb调试。但是not stripped的情况并不能说明能够被调试。

03

使用方法

    3.1 启动调试

在开发中可以将源码和可执行文件拷贝到某一目录下,使用gdb启动进程进行调试,也可以不拷贝源码和可执行文件,使用NFS挂载到编译环境执行调试;在现场环境中使用ps获取进程的pid,然后gdb –p pid执行在线调试。

    离线调试:

gdb 进程名

gdb –tui 进程名

    在线调试:

ps –A | grep 进程名

gdb –p pid/gdb attach pid

说明:使用-tui参数可以将调试窗口分为两部分:上面是源码,下面是调试信息,使用Ctrl+n/Ctrl+p或者方向键进行翻页。

    带参数调试:

1、启动的时候带上参数

gdb --args xxx 参数

2、启动之后 run 带上参数

# gdb xxx

(gdb)run 参数

3、启动之后 set args 设置参数

# gdb xxx

(gdb) set args 参数

 core文件调试

当程序core dump时,可能会产生core文件,它能够很大程序帮助我们定位问题。但前提是系统没有限制core文件的产生。可以使用命令limit -c查看:

$ ulimit -c

如果结果是0,即便程序core dump了也不会有core文件留下。我们需要让core文件能够产生:

ulimit -c unlimied  #表示不限制core文件大小

ulimit -c 10  #设置最大大小,单位为块,一块默认为512字节

上面两种方式可选其一。第一种无限制,第二种指定最大产生的大小。

针对生成core文件进行调试,可以采用在线加载和离线加载的方式,如下:

gdb 可执行文件 core文件

    3.2 SET命令

命令

说明

set args 参数值

设置进程启动时的参数,等同于:run参数

set print系列

set print pretty on | off:是否格式化输出

set print obj on | off:是否以对象形式打印变量

set print address on | off:是否显示参数地址

set print array on | off:是否显示数组

set print elements 整型值:主要是设置数组的,如果你的数组太大了,那么就可以指定一个来指定数据显示的最大长度,当到达这个长度时,GDB就不再往下显示了。如果设置为0,则表示不限制。

set print union on | off

set 变量=value

强制设置某个变量的值

set environment name=value

强制设置环境变量的值

set scheduler-locking on | off

设置为ON,开启单线程调试模式,其余线程均挂起

注:有时候使用p打印调试信息不完整或者不便于阅读,可以使用set print elelent 0和setprint pretty on设置。

 3.3 handle命令

handle命令

handle SIGUSR1 nostop noprint

handle SIGUSR2 nostop noprint

handle SIGPIPE nostop noprint

handle SIGALARM nostop

handle SIGHUP nostop

handle SIGTERM nostop noprint

注:设置GDB调试时对信号的相关动作。

 3.4 设置断点

打断点还是比较有技巧的,虽然有很多打断点的方法,但是实际调试中一般就使用以下几种:

   函数打断点:b 函数名

   某一行打断点:b 源文件:行号

  条件断点:

break 断点 if 条件

continue 断点编号(执行一次表示设定,再次执行表示取消)

continue 断点编号 条件

注:条件断点非常有用,实际调试中往往需要调试特定场景下函数调用关系,此时就需要设置断点触发的条件。

 查看断点:info breakpoint/info break/info b

  删除断点:delete 断点号/delete(删除所有断点)

禁用/开启断点:disable/enable breakpoint

ignore:

断点条件的一个特殊用法是,程序只有在到达断点一定次数之后才会停止,此时可以使用指令:

ignore 断点编号 次数

ignore 2 10触发断点10次后才会停止,每次触发断点count自动减1

说明:打完断点是不是执行continue就可以等待着运行到断点了呢?不一定,有时候断点处代码的执行需要外部出发,比如web发送特定消息后才可以触发执行,如果一直等待没有消息出发永远执行不到断点处,此时就需要结合自己的业务逻辑,手动设置出发条件。

    3.5 执行程序

执行程序的方法有两种:一种是从main函数开始执行逐步分析,一种是执行到断点处。

   重新运行:r/run

 继续执行:c/continue

  单步执行:n/next/next N(执行N次next)

    单步进入:step(遇到函数进入函数内部,退出函数时使用finish)

    结束函数:finish

    强制返回:return(忽略当前未执行的部分,强制返回)

   3.6 显示堆栈

(gbd) backstrace/bt

有时候跳转的次数太多,不知道具体调用的层级关系了,可以使用bt查看堆栈,该命令会产生一张列表,包含着运行过程和相关的参数。

   3.7 变量操作

  设置变量:set 变量=表达式

在调试的时候,有时候需要设置一些假数据查看对应输出,比如根据布尔值查看流程执行情况,此时就需要在执行到指定位置时手动设置一下数据的取值。

   监控变量:

watch 变量 (数值改变时暂停运行)

awatch (被访问或改变时暂停运行)

rwatch   (被访问时暂停运行)

有时候我们需要观察一个变量的变化过程,比如一个全局变量如何初始化,如何调用的,这就需要使用watch监控变量。

  变量类型:

ptype var 变量类型

whatis var 显示一个变量var的类型

   打印变量/表达式:

打印变量:p 变量

  打印字符/表达式:p “%s”,字符/表达式

 格式化输出:p/格式控制符 打印内容

说明:

gdb可支持的变量显示格式有:

x:按16进制格式显示变量

d:按10进制格式显示变量

u:按16进制格式显示无符号整型

o:按8进制格式显示变量

t:按2进制格式显示变量

c:按字符格式显示变量

f:按浮点数格式显示变量

也可以使用x(Examination)来打印需要显示的字符信息,格式如下:

x/格式 地址

格式(可选)一般是NFU:

1、N表示重复次数(表示显示内存的长度,也就是说从当前向后显示几个地址的内容)

2、F表示显示格式

3、U表示单位(b:字节,h:半字[2字节],w:字[4字节,默认],g:双字[8字节])。表示多少个字节作为一个值取出来,如果不指定的话,GDB默认是1个byte,当我们指定了字节长度后,GDB会从指定内存的地址开始,读取指定字节,并把其作为一个值取出来。

参数u可使用下面字符代替:

b:表示单字节

h:表示双字节

w:表示四字节

g:表示八字节

    3.8 调试函数

    disassemble    

可以使用反汇编的指令disassemble去探究究竟在函数中发生了哪些操作,具体如下:

1、disassemble

2、disassemble 程序计数器

3、disassemble 开始地址 结束地址

格式1表示反汇编当前整个函数,格式2表示反汇编计数器所在函数的整个函数,格式3表示反汇编从开始地址到结束地址的部分。

    call

强制调用函数:call 表达式

   3.9 退出调试

    q/quit

在执行到断点后,采用q/quit指令退出。

04

多进程调试

    4.1 配置

    detach-on-fork

该属性决定了gdb是同时调试父子进程,还是在fork了子进程之后,将子进程分离出去。

on:子进程(或者父进程,取决于gdb在初始时,要调试的进程,也就是follow-fork-mode的值)

off:同时调试父子进程,一个进程处于被调试的状态,而另一个则被gdb挂起

设置:set detach-on-fork on/off

    follow-fork-mode

该属性决定了gdb在进程调用fork之后的行为。

set follow-fork-mode parent:默认情况下,在调用fork之后,gdb选择跟随(也就是调试)父进程,而子进程则在处于运行的状态(此时父进程处于阻塞的状态)。

set follow-fork-mode child:fork之后gdb选择调试子进程,而父进程处于运行的状态。

    4.2 查看进程

查看当前调试的进程:info inferiors

05

多线程调试

    5.1查看线程

查看线程:info threads

注:输出信息前面有“*”表示调试的当前线程(一般thread切换线程后查看)。

有的程序会在运行过程中主线程创建多个子线程,所以前后执行info threads显示的线程数是会动态变化的。

   5.2 查看线程堆栈

  查看所有线程堆栈:thread apply all bt

    查看指定线程堆栈:thread apply thread1 thread2... bt

   5.3 切换线程

    切换线程:thread N

注:通过打印counter,可以看到多个线程都是在运行的,如果想要让其他线程处于停止状态,只有当前调试的线程执行,可以采用set scheduler-locking on。

    5.4 阻塞线程

阻塞其他线程,仅调试当前线程工作:

set scheduler-locking [on|off|step]

运行指定线程并允许其他线程并行执行:

thread apply N command

06

总结

对于C语言开发,必须熟练使用gdb进行调试,这可以帮助我们快速定位问题并解决问题,在开发中可以帮助我们及时找到测试出现的问题,在现场问题中如果日志打印不是很充分,日志信息量不够的情况下,gdb调试显得非常重要。

在实际应用中,我们通常是利用gdb分析core文件,这就需要结合寄存器,汇编,内存相关知识综合分析,后面会详细介绍相关分析技巧。

你们点点“分享”,给我充点儿电吧~

gdb x命令_详解gdb的使用技巧相关推荐

  1. centos7python命令_详解Linux Centos7下安装Python的方法

    1.查看是否已经安装Python Centos7默认安装了python2.7.5 因为一些命令要用它比如yum 它使用的是python2.7.5. 使用python -V命令查看一下是否安装Pytho ...

  2. awk -f 分隔符 命令_详解!!!awk参见使用命令

    今天介绍Linux常见的一个命令awk,一门模式匹配的编程语言,因为它的主要功能是用于匹配文本并处理,同时它有一些编程语言才有的语法,例如函数.分支循环语句.变量等等.当然比起我们常见的编程语言,aw ...

  3. linux打开文件命令_详解Linux中3个文件查找相关命令

    来自:民工哥技术之路 1.which命令 我们经常在linux要查找某个文件,但不知道放在哪里了,可以使用下面的一些命令来搜索: which  查看可执行文件的位置. whereis 查看文件的位置. ...

  4. centos 添加路由命令_详解CentOS 6.4 添加永久静态路由所有方法汇总

    CentOS添加永久静态路由,具体如下: 在使用双网卡,同时使用2个网关的时候就需要加一条静态路由了.当然还有很多时候会需要加路由. 操作系统版本centos-6.4 64bit 一:使用route ...

  5. python调用cmd执行命令_详解python调用cmd命令三种方法

    目前我使用到的python中执行cmd的方式有三种 使用os.system("cmd") 该方法在调用完shell脚本后,返回一个16位的二进制数,低位为杀死所调用脚本的信号号码, ...

  6. mysql8 重启命令_详解MySQL8.0+常用命令

    开启远程访问 通过以下命令开启root用户远程访问权限: CREATE USER 'root'@'%' IDENTIFIED BY 'password'; GRANT ALL ON *.* TO 'r ...

  7. css label 居中布局_详解 CSS 居中布局技巧

    水平居中元素:通用方法,元素的宽高未知 方式一:CSS3 transform .parent { position: relative; } .child { position: absolute; ...

  8. 华三交换机ping大包命令_如何Ping大包命令_Ping大包命令格式详解-win10铺

    如何Ping大包命令?Ping大包命令格式详解如下: ping全称Packet Internet Grope-英特网包探索器,是一个Windows自带可执行命令,主要用来检测网络是否通畅或者网络链接速 ...

  9. 强大的strace命令用法详解

    强大的strace命令用法详解_Linux教程_Linux公社-Linux系统门户网站 strace是什么? 按照strace官网的描述, strace是一个可用于诊断.调试和教学的Linux用户空间 ...

最新文章

  1. 平流式初沉池贮砂斗计算_水处理相关计算软件大全,提高工作效率必备
  2. 15.PAE分页(2-9-9-12)
  3. 1、数据库为什么需要备份?
  4. Android Studio运行报错Instant Run requires 'Tools | Android | Enable ADB integration' to be enabled
  5. python3下使用requests实现模拟用户登录 —— 基础篇(马蜂窝)
  6. mysql 设置 server id_MySQL中如何设置 auto_increment 重新计数 主键id从1开始
  7. Carrier Configuration in Android 6.0 文档翻译
  8. 计算机的软硬件发展进程,计算机软件的发展演变简介
  9. 二叉树层序遍历算法实现
  10. QTP11.0安装步骤及需要注意事项
  11. php劳保管理系统,《劳保用品管理系统》用盟威快速开发平台开发的应用实例
  12. mapreduce求平均值
  13. USACO 土地购买
  14. Cocos2d-x《雷电大战》(4)-策略模式实现不同子弹切换!!
  15. 使用素描图像识别人脸
  16. VUE常用指令v-xxx
  17. wind10MySQL闪退什么密码_小编调解技术编辑应对win10系统Mysql输入密码后闪退的操作办法的解决教程...
  18. Python爬取张家界风景美图
  19. 那个“支付宝锦鲤”女孩,现在变得怎么样了?你肯定想象不到
  20. CUMT网络安全课程复习

热门文章

  1. 报名 | 腾讯组织的区块链技术沙龙,本周六在深圳!
  2. Syslog系统日志配置
  3. Unsupported Hardware Detected
  4. 游戏数仓分析(三)SpringBoot项目对数据进行可视化展示,每日注册用户
  5. 练习:每一分钟产生一个文件,保存本分钟内所有数字之和。
  6. leetcode 437. Path Sum III | 437. 路径总和 III(DFS,前缀和)
  7. 【Modelsim零基础入门】verilog仿真程序:1-bit A+B
  8. C# 什么是【事件驱动】
  9. 使用IBM Blockchain Platform extension开发你的第一个fabric智能合约
  10. c++堆栈溢出怎么解决_c语言进阶:堆栈原理揭秘