当前位置: 首页 > article >正文

Linux 调试工具:gdb

调试复习

调试可谓是 “贯穿” 了程序员的一生,调试的重要性,就不再赘述啦!如果你还不知道什么是调试,可以看看 Windows 系统的 Visual Studio 是如何调试的:➡️ visual stuudio 使用调试技巧

下载调试软件 gdb

yum install gdb -y

gdb 的使用

gdb 的使用非常简单:

gdb 可执行文件

这是一段简单的代码:

#include<stdio.h>

int main()
{
    printf("hello gdb\n");
    return 0;
}

这是 makefile 文件:

test:test.c
	gcc -o $@ $^ -std=c99
.PHONY:clean
clean:
	rm -f test

make 生成可执行文件之后,我们来看看是否能够启动 gdb 调试:
在这里插入图片描述
我们看到出现了报错:可执行文件中没有调试信息。这是因为 linux 环境下 gcc 形成的可执行程序默认是以 release 的形式发布的,release 版本的可执行程序当然不包含调试信息啦!
于是,我们需要以 debug 的方式发布可执行程序,只需要加一个 -g 的选项就可以啦!

# 这是 makefile 文件
test:test.c
	gcc -o $@ $^ -g -std=c99
.PHONY:clean
clean:
	rm -f test

那么如何看到可执行程序中是否有调试信息呢?我们都知道 linux 环境下的可执行程序是一种 elf 格式的文件,我们只要打开这个 elf 格式的文件,就能看到啦!

readelf -S 可执行程序

我们可以看到 debug 方式发布的可执行程序确实多了调式信息。(文件比较长,下图中只截取了一部分)
在这里插入图片描述

调试前的准备

我们来写一个简单的程序,作为调试之前的准备工作吧!
test.c

#include<stdio.h>
#include "function.h"

int multiple(int x, int y)
{
	int ret = x * y;
    return ret;
}
int main()
{
    int a = 2, b = 3;
    int sum = 0;
    sum = Add(a, b);
    printf("a + b: %d\n", sum);
    
    int times = multiple(a, b);
    for(int i = 0; i < times; i++)
    {
    	printf("hello gdb %d\n", i);
    }
    return 0;
}

function.h

#pragma once

int Add(int x, int y);

function.c

#include "function.h"

int Add(int x, int y)
{
    return x + y;
}

调试命令一览

gdb 可执行程序   #开始调试
quit/q          #退出调试
l 数字          #显示代码,默认是 10 行
r               #运行程序
b 行号          #在main函数所在文件的指定行打断点
b 文件名:行号    #在指定文件的指定行号打断点
b 函数名         #在指定函数的第一行代码处打断点
info b          #查看所有断点信息
d 断点编号       #删除断点

# r 开始调试之后

n               #逐过程运行
s               #逐语句执行
p 变量           #查看变量的值
display 变量     #变量值常显示,类似于 visual studio 的监视窗口
undisplay 变量   #取消变量的长显示
untill 行号      #在函数内跳转到指定行
finish          #执行完当前行所在的函数
c               #运行到下一个断点处
disable 断点编号 #禁用指定断点
enable 断点编号  #恢复禁用的断点
set var 变量=#类比 visual studio 中的条件断点
bt              #查看调用堆栈
info locals     #查看本地变量(局部变量)

下面我会选择几个比较不好理解的讲讲

l 数字

l 默认显示 10 行,gdb 会记住上一条命令,回车就可以继续执行上一条命令。
在这里插入图片描述

b 文件名:行号

这个命令在多文件的调试中可能会用到:
在这里插入图片描述

d 断点编号


断点编号是什么呢?查看断点编号需要使用 info b 命令:
在这里插入图片描述
其中这个 Num 就是断点编号啦!


在这里插入图片描述
可以看到删除断点之后就查看不到断点的信息啦!


删除刚刚的断点之后我们再打一个断点,发现断点编号并不是 1,说明断点编号是递增的!
在这里插入图片描述

display 变量

可以动态显示一个变量的内容,类似于监视窗口。
我们使用 r 运行程序,开始调试。display num 看到:sum = 0 没问题,然后 n 逐过程运行。发现 sum 变成了 5。这就相当于监视窗口不是嘛!
在这里插入图片描述

finish

执行完当前行所在的函数,这是什么意思呢?我们在第六 6 行打一个断点,看看效果就知道了!
在这里插入图片描述
效果就是直接完成了当前行所在函数的运行

disable 断点编号

这个命令可以禁用断点,visual studio 也是可以的!
在这里插入图片描述
禁用 1 号断点之后,我们查看断点信息,发现 Enb 属性变成了 n。这就表示这个断点被禁用了!

set var 变量=值

我们在 19 行打一个断点,然后运行程序,开始调试,再然后 set var i=3 运行之后,我们发现打印的就是 hello gdb 3 这是不是和 visual studio 中的条件断点一个味儿!
在这里插入图片描述


http://www.kler.cn/a/149281.html

相关文章:

  • 基于Spring Boot与Redis的令牌主动失效机制实现
  • 图论-代码随想录刷题记录[JAVA]
  • 多进程/线程并发服务器
  • CSS回顾-长度单位汇总详解
  • 三维测量与建模笔记 - 特征提取与匹配 - 4.2 梯度算子、Canny边缘检测、霍夫变换直线检测
  • PostgreSQL分区表:基础语法与运维实践
  • 使用shell快速查看电脑曾经连接过的WiFi密码
  • 记一次简单的PHP反序列化字符串溢出
  • 交流负载的功能实现原理
  • 各种排序算法
  • sed应用
  • 视觉CV-AIGC一周最新技术精选(2023-11)
  • 【面经八股】搜广推方向:面试记录(四)
  • git commit 撤销的三种方法
  • Kotlin学习——kt里的集合,Map的各种方法之String篇
  • QT6 Creator编译KDDockWidgets并部署到QT
  • C#通过NPOI 读、写Excel数据;合并单元格、简单样式修改;通过读取已有的Excel模板另存为文件
  • SP3109 STRLCP - Longest Common Prefix 题解
  • 0基础学习VR全景平台篇第123篇:VR视频航拍补天 - PR软件教程
  • 前端---CSS篇(详解CSS)
  • 微服务--03--OpenFeign 实现远程调用 (负载均衡组件SpringCloudLoadBalancer)
  • 【 Kubernetes 风云录 】- Istio 应用多版本流量控制
  • 【古月居《ros入门21讲》学习笔记】17_launch启动文件的使用方法
  • dockerfile指令学习
  • ubuntu改window任务栏
  • Leetcode—2336.无限集中的最小数字【中等】