【Linux】Linux调试器----gdb/cgdb

目录

  • 前言
  • 一、debug和release
  • 二、gdb/cgdb的使用
    • [1. 启动bdg/cgdb](#1. 启动bdg/cgdb)
    • [2. 退出](#2. 退出)
    • [3. 代码查看(list/l)](#3. 代码查看(list/l))
    • [4. 运行程序(r)](#4. 运行程序(r))
    • [5. 设置断点](#5. 设置断点)
    • [6. 查看断点](#6. 查看断点)
    • [7. 删除断点](#7. 删除断点)
    • [8. 禁用/启动断点](#8. 禁用/启动断点)
    • [9. 逐语句/逐过程](#9. 逐语句/逐过程)
    • [10. 查看变量](#10. 查看变量)
    • [11. 运行到指定行](#11. 运行到指定行)
    • [12. 执行到函数返回](#12. 执行到函数返回)
    • [13. 从断点处运行到下一个断点](#13. 从断点处运行到下一个断点)
  • 三、gdb/cgdb调试技巧
    • [1. watch](#1. watch)
    • [2. set var](#2. set var)
    • [3. 条件断点](#3. 条件断点)

前言

【Linux】自动化构建--make/Makefile详情请点击,今天继续介绍【Linux】Linux调试器----gdb/cgdb

一、debug和release

  1. 在Linux中编译器(gcc/g++)默认生成的可执行文件是release版本的(无调试信息),无法调试

  2. 如果想要使用gdb/cgdb来调试代码,必须要使用debug(包含调试信息)版本,gcc/g++默认是生成release版本,我们使用gcc -o test-debug test.c -g指令来指定生成debug版本的可执行程序

  3. 由于debug版本在可执行性程序内部添加了调试信息,因此debug版本比release版本所占空间大

可执行程序不仅仅是二进制文件,它的内部是有固定格式的,指令:readelf -S 可执行文件名,查看可执行文件的格式(ELF格式),我们还可以借助管道和grep对二进制格式信息进行搜索,-i :表示忽略大小写查找

由于默认是生成release版本,所以test中无调试信息,没有debug信息,test-debug是debug版本,所以查找到了debug相关信息

二、gdb/cgdb的使用

cgbd 类似于是gdb 的"现代化"终端界面,拥有了图形化界面,因此建议新手先使用cgbd调试,熟练掌握相关指令和操作后再使用gdb,这里使用cgdb做演示

1. 启动bdg/cgdb

  1. bdg/cgdb 可执行文件名:启动bdg/cgdb
  2. 使用cgdb会直接进入两个窗口的页面,上面窗口是代码,下面窗口是cbdg指令区,这样调试的时候能看到代码以及调试进度

2. 退出

  1. quit/q退出gdb/cgdb

3. 代码查看(list/l)

  1. l n:会打印上下共n行代码,gdb会记录最近一次的命令,如果超查看完整代码,可以输入命令:l 0再不停的按回车键即可将全部代码内容显示
  2. l 函数名:查看函数代码

4. 运行程序(r)

  1. r:从程序开始连续执行,如果有断点执行到第一个断点处,如果没有断点,执行到程序结束

5. 设置断点

  1. b n:表示再第n行设置断点
  2. b 文件名:行号,表示在文件行号为n的位置打断点
  3. b 函数名:在函数开头设置断点

使用gdb并不能很直观的看到断点的设置,我们使用cgdb来查看断点设置后的效果

  1. 我们可以看到,20行设置断点后,20行行标数字20变成红色
  2. 在20行打下断点,使用r指令运行程序

6. 查看断点

info b:查看断点信息,根据断点设置的先后顺序编号

7. 删除断点

d n:n表示断点序号(不是行号)

8. 禁用/启动断点

  1. disable n:n代表断点序号,禁用断点
  2. enable n:n代表断点序号,启动断点

9. 逐语句/逐过程

逐语句:进入函数

逐过程:把函数当成一个整体语句(不进入函数里面)

  • vs中,逐过程F10,逐语句F11
  • cdgb中,逐过程 n(next)逐语句 s(step)
  1. 逐过程 n(next)
  2. 逐语句 s(step)

10. 查看变量

  1. p 变量:调试过程中,查看变量的值并将其打印出来
  2. 用p命令每次调试的时候都必须要p 变量才会打印变量值,有什么办法能在调试的时候直接显示查看变量的值吗?
  3. 使用display 变量跟踪显示变量,类似于vs中的监视窗口
  4. 取消对变量的跟踪显示使用指令:undisplay 编号(不能使用变量名)

11. 运行到指定行

在函数中如果有一个循环语句,我们想直接一步运行完这个循环语句(这个区域的代码),使用指令:until 行号:直接运行到该行号位置

12. 执行到函数返回

finish指令:直接执行完该函数

13. 从断点处运行到下一个断点

指令:c,从当前位置运行到下一个断点处

注意:调试步骤

  1. 首先使用until && finish && c来大致缩小错误程序的范围
  2. 再使用逐语句(s)、逐过程(n)来确定具体错误代码

三、gdb/cgdb调试技巧

1. watch

  1. 执行时监视⼀个表达式(如变量)的值。如果监视的表达式在程序运行期间的值发生变化,gdb会暂停程序的执行
  2. 其本质也是一个断点,只不过该断点生效的条件是watch的变量的值发生变化才会触发

  • 如果你有⼀些变量不应该修改,但是你怀疑它修改导致了问题,你可以watch它,如果变化了,就会通知你(监视变量的变化)

2. set var

  1. set var 变量名:在debug过程中,修改变量的值(在我们知道问题代码是某个变量影响导致的,直接在gdb/cgdb中修改,如果修改后代码没问题,那么就能直接确定问题)

3. 条件断点

  1. 条件断点命令:b 行号 if 断点触发条件
  2. 条件断点其本质也是断点,只不过要触发条件之后才生效
  1. 将已存在的断点(普通)改为条件断点
    使用指令:condition 普通断点的序号 条件
相关推荐
btyzadt2 小时前
Ubuntu防火墙端口管理指南
linux·运维·服务器
野熊佩骑3 小时前
CentOS7二进制安装包方式部署K8S集群之CA根证书生成
linux·运维·docker·云原生·容器·kubernetes·centos
每天更新3 小时前
linux内核时间&定时器&延时
linux·运维·服务器
杜子不疼.3 小时前
【Linux】冯 • 诺依曼体系结构
linux·运维·服务器
门前灯3 小时前
Linux系统之msgexec 命令详解
linux·运维·服务器·msgexec
简一之学无止境3 小时前
Linux中信号量semaphore的实现
linux
東雪蓮☆5 小时前
MySQL 全量 + 增量备份脚本(RPM 安装)实践与问题解析
linux·运维·mysql
落羽的落羽5 小时前
【Linux系统】快速入门一些常用的基础指令
linux·服务器·人工智能·学习·机器学习·aigc
大白的编程日记.12 小时前
【Linux学习笔记】线程概念和控制(二)
linux·笔记·学习