Linux下的调试器 : gdb指令详解

🪐🪐🪐欢迎来到程序员餐厅💫💫💫
          主厨:邪王真眼
主厨的主页:Chef‘s blog  
所属专栏:青果大战linux
总有光环在陨落,总有新星在闪烁

gdb是什么

        gdn是linux下的一个开源的命令行调试器,它可以帮助程序员在调试程序时跟踪程序运行过程中的错误。它可以用于C、C++、Fortran、汇编语言等多种编程语言。通过GDB,你可以在程序运行时中断程序的执行,查看和修改变量的值,设置断点,单步执行代码,打印函数调用栈等操作。

       基于gdb强大的调试能力,我们可以快速定位程序运行过程中的错误。现在就让我们来学习它的使用吧。


调试信息

       程序的发布方式有两种,debug模式和release模式 ,那么我们之前gcc编译生成的可执行文件是那种类型呢?我们要知道生成的可执行文件是二进制文件,使用了ELF格式,而readelf指令就可以用来查看ELF文件的信息。
我们先创建一个test1.c文件
#include<stdio.h>
int add(int i)
{
    int sum=0;
    for(int j=0;j<=i;j++)
        sum+=j;
        return sum;
}
int main()
{
    int sum=0;
    for(int i=0;i<=10;i++)
    {
        sum+=add(i);
    }
    printf("%d\n",sum);
    return 0;
}

现在对他进行gcc,因为我们gcc默认不支持c99的语法,所以要加上-std=c99来让他支持

gcc -o test1.exe test1.c -std=c99

可以看到文件生成了,并且可以正常运行,接下来我们来查看他的调试信息,即debug信息
readelf -S test1.exe |grep debug

        以上指令,管道左侧用于输出可执行文件内的内容,右侧用于筛选含有debug字段,最后该指令什么也没有输出,说明gcc默认生成的可执行文件不包含debug信息,无法被调试。

  • 得出结论:

       gcc默认发布的是release版本,要想发布debug版本,必须在源代码生成二进制程序的时候, 加上 -g 选项

gcc -o test1.exe.debug test1.c -std=c99 -g

文件正常生成并且运行正确

输入指令查看调试debug信息
readelf -S test1.exe.debug |grep debug

成功发现debug信息

  1 #include<stdio.h>
  2 int add(int i)
  3 {
  4     int sum=0;
  5     for(int j=0;j<=i;j++)
  6         sum+=j;
  7         return j;
  8 }
  9 int main()
 10 {
 11     int sum=0;
 12     for(int i=0;i<=10;i++)
 13     {
 14         sum+=add(i);
 15     }
 16     printf("%d\n",sum);
 17     return 0;                                                                                                                                                                                                
 18 }

gdb调试过程

进入gdb

输入指令

 gdb test1.exe.debug

出现一堆信息后左下角出现(gdb)说明进入了调试过程
输入:ctrl + d quit 命令即可退出

查看代码信息

  • 指令:l n

以第n行为中心,显示10行代码

  • 指令l
从上次显示的代码结尾开始,显示10行
展示:
输入 l  5,显示周围10行
再输入l,显示接下来10行,但是因为我代码不足10行所以就只显示剩下的部分
l+函数名,以该函数为中心,显示10代码
注意gdb会自动记录你最近一次的指令,如果你直接输入回车,他就会执行上一次的指令

断点:

  • b +行号
在该行设置一个断点
(gdb) b 12
Breakpoint 1 at 0x40055a: file test1.c, line 12.

gdb提醒我们 把断电设置到了test1.c文件的第12行

  • b +函数
在该函数定义的开头设置一个断点
(gdb) b add
Breakpoint 2 at 0x400524: file test1.c, line 4.

gdb提醒我们 把断电设置到了test1.c文件的第12行,因为add函数的定义是从第四行开始的

b是break的缩写,我们用break代替b也是可以的

(gdb) break 16
Breakpoint 3 at 0x40057a: file test1.c, line 16.
  • info b

显示断点信息

(gdb) info b
Num     Type           Disp Enb Address            What
1       breakpoint     keep y   0x000000000040055a in main at test1.c:12
2       breakpoint     keep y   0x0000000000400524 in add at test1.c:4
3       breakpoint     keep y   0x000000000040057a in main at test1.c:16
  1. Num那一列是断点的编号
  2. type那一列是类型(断点)
  3. Enb表示断点关闭或启动状态
  4. what是断点位置
  • d+断点编号

表示删除该断点,d是delete的缩写,二者可以相互替代

展示:可以发现我们成功删除了第三个断点

(gdb) delete 3
(gdb) info b
Num     Type           Disp Enb Address            What
1       breakpoint     keep y   0x000000000040055a in main at test1.c:12
2       breakpoint     keep y   0x0000000000400524 in add at test1.c:4
  • disable+断点编号

关闭该断点,注意是关闭不是删除

展示:可以发现此时2号断点的状态变成了关闭

(gdb) disable 2
(gdb) info b
Num     Type           Disp Enb Address            What
1       breakpoint     keep y   0x000000000040055a in main at test1.c:12
2       breakpoint     keep n   0x0000000000400524 in add at test1.c:4
  • enable+断点编号

开启断点,与disable相对

可以发现此时2号断点的状态变成了开启

(gdb) enable 2
(gdb) info b
Num     Type           Disp Enb Address            What
1       breakpoint     keep y   0x000000000040055a in main at test1.c:12
2       breakpoint     keep y   0x0000000000400524 in add at test1.c:4

运行:

  • r:

run的缩写,使用run也可以

开始运行程序,直到程序结束或遇到断点

我们先把断点关了

输入r指令,发现程序直接运行到结束
(gdb) r
Starting program: /home/qingguo/project7_gdb/test1.exe.debug 
220

再把断点都打开,发现程序停在了第一个断电处

(gdb) r
Starting program: /home/qingguo/project7_gdb/test1.exe.debug 

Breakpoint 1, main () at test1.c:12
12	    for(int i=0;i<=10;i++)

我们继续输入r

The program being debugged has been started already.
Start it from the beginning? (y or n) 

它说程序已经启动了,是否要重新启动,可以看出r不能帮我们进入后面的程序

  • c

是continue的缩写

继续执行程序直到程序结束,或者遇到下一个断点,

(gdb) continue
Continuing.

Breakpoint 2, add (i=0) at test1.c:4
4	    int sum=0;
  • 逐过程-n

我们重新执行r,再输入n

我们在第12行设置了断点,所一程序现在这里停了下来,接着输入n,从第12行进入了第14行,这是因为13行是一个上括号{,这在gdb看来是不需要进行操作的,所以跳过了

Breakpoint 1, main () at test1.c:12
12	    for(int i=0;i<=10;i++)
(gdb) n
14	        sum+=add(i);
(gdb) 

        相信大家都记得逐过程的特点是不会进入函数内部,而会把调用函数所在语句当成一条语句。我们来演示一下

(gdb) n
14	        sum+=add(i);
(gdb) n

Breakpoint 2, add (i=0) at test1.c:4
4	    int sum=0;

唉?不是,哥们,怎么进去了,这怎么想都进不去吧

        其实是因为我们最开始在add函数里放了断点,所以输入n后在执行函数内容时程序会被停下来,我们去掉断点就好了

12	    for(int i=0;i<=10;i++)
(gdb) n
14	        sum+=add(i);
(gdb) 
12	    for(int i=0;i<=10;i++)
  • s逐语句调试

会进入函数内部

12	    for(int i=0;i<=10;i++)
(gdb) s
14	        sum+=add(i);
(gdb) s
add (i=3) at test1.c:4
4	    int sum=0;

finish执行到当前函数结束,有返回值还会告诉你返回值

(gdb) finish
Run till exit from #0  add (i=3) at test1.c:4
0x000000000040056d in main () at test1.c:14
14	        sum+=add(i);
Value returned is $1 = 6
  •  until +行数 

输入r后程序开始运行,在输入until+行数可以直接运行到该行

(gdb) until 14
main () at test1.c:14
14	        sum+=add(i);

查看变量:

  • p+变量名

显示该变量的值,

12	    for(int i=0;i<=10;i++)
(gdb) p i
$2 = 3
  • display+变量名

跟踪查看一个变量,每次停下来都显示它的值

(gdb) display i
5: i = 5
(gdb) display sum
6: sum = 35
(gdb) n
14	        sum+=add(i);
6: sum = 35
5: i = 6
  • undisplay+编号

取消对先前设置的那些变量的跟踪

可以发现每次显示的i和sun左边都有一个编号,一个是5一个是6,我们输入undisplay 5

(gdb) n
12	    for(int i=0;i<=10;i++)
6: sum = 84
  • set var
在程序运行时修改变量的值
(gdb) set var i=8
(gdb) p i
$5 = 8
  • breaktrace(bt)
查看各级函数调用及参数
(gdb) bt
#0  main () at test1.c:14

我们现在再main函数中,下面使用until跳转到add里

(gdb) bt
#0  add (i=0) at test1.c:4
#1  0x000000000040056d in main () at test1.c:14

可以看到#0后面是add函数,而#1后面是main函数,说明main函数里调用了add,并且我们当前处于add中

  • infoi) locals
查看当前栈帧局部变量的值
(gdb) info locals
sum = 0
(gdb) i locals
sum = 0

        我们今天学习了gdb调试时会用到的十几条指令,下去记得好好复习,才能在以后调试的时候合理使用。


🥰创作不易,你的支持对我最大的鼓励🥰
🪐~ 点赞收藏+关注 ~

e3ff0dedf2ee4b4c89ba24e961db3cf4.gif

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:/a/646352.html

如若内容造成侵权/违法违规/事实不符,请联系我们进行投诉反馈qq邮箱809451989@qq.com,一经查实,立即删除!

相关文章

SQL注入:原理及示例讲解,配置mysql环境变量,pikachu靶场搭建

SQL注入原理 SQL注入&#xff08;SQL Injection&#xff09;是一种代码注入技术&#xff0c;攻击者通过将恶意的SQL代码插入到应用程序的输入字段中&#xff0c;诱使后台数据库执行这些恶意代码&#xff0c;从而对数据库进行未授权的操作。常见的操作包括获取敏感数据、篡改数…

Liunx基本指令以及权限(个人笔记)

Linux指令和权限 1.指令1.1ls指令1.2pwd命令1.3cd指令1.4touch指令1.5mkdir指令1.6rm指令1.7man指令1.8cp指令1.9mv指令1.10cat指令1.11less指令1.12head指令1.13tail指令1.14date显示1.15Cal指令1.16find指令1.17grep指令1.18zip/unzip指令1.19tar指令1.20bc指令1.21uname -r指…

Python数据可视化(五)

实现GUI效果 借助 matplotlib&#xff0c;除可以绘制动画内容外&#xff0c;还可以实现用户图形界面的效果&#xff0c;也就是 GUI 效果。 GUI是用户使用界面的英文单词首字母的缩写。接下来&#xff0c;我们就以模块widgets中的类RadioButtons、 Cursor 和 CheckButtons 的使用…

属于程序员的浪漫,一颗会跳动的心!!!

绘制一颗会跳动的心❤ 嘿嘿 可以说是程序员的专属浪漫了吧&#xff0c;就像点燃一颗LED灯一样&#xff1f;&#xff08;我瞎说的啊&#xff0c;大家别当真&#xff0c;我很菜的&#xff01;&#xff01;&#xff01;&#xff01;&#xff09; 程序就在下面啦&#xff0c;然…

​✨聚梦AI绘图插件-for photoshop(基于ComfyUI) 内测版V0.1发布

&#x1f388;背景 photoshop本身是有AI生成能力的&#xff0c;不过限于种种原因&#xff0c;国内使用很不方便。 photoshop也是有AI插件的&#xff0c;不过大多安装起来比较复杂&#xff0c;或者&#xff0c;干脆就会收费。 所以我们做了一个免费的AI插件&#xff0c;期望能…

Vue.js条件渲染与列表渲染指南

title: Vue.js条件渲染与列表渲染指南 date: 2024/5/26 20:11:49 updated: 2024/5/26 20:11:49 categories: 前端开发 tags: VueJS前端开发数据绑定列表渲染状态管理路由配置性能优化 第1章&#xff1a;Vue.js基础与环境设置 1.1 Vue.js简介 Vue.js (读音&#xff1a;/vju…

如同“水生态”的存储引擎|OceanBase数据转储合并技术解读(一)

本系列文章主要围绕 OceanBase数据库存储引擎中的转储合并进行解读&#xff0c;涉及到数据存储、转储合并、数据校验等方面的内容&#xff0c;旨在让读者了解OceanBase数据库的存储引擎中与转储合并有关的各种概念&#xff0c;帮助读者更好地理解OceanBase数据库的存储技术原理…

20240526怎样将windows的屏幕复制到第二屏

百度&#xff1a;WIN10 第二显示器 COPY https://zhidao.baidu.com/question/761454546683111004.html 20240526怎样将windows的屏幕复制到第二屏  我来答 分享 举报 2个回答#热议# 海关有哪些禁运商品&#xff1f;查到后怎么办&#xff1f; 华硕服务 2022-07-05 百度认证:…

C++模板——函数模板和类模板

目录 泛型编程 函数模板 函数模板概念 函数模板的定义和语法 函数模板的工作原理 函数模板的实例化 隐式实例化 显示实例化 函数模板的匹配原则 类模板 类模板的定义格式 类模板的实例化 泛型编程 什么是泛型编程&#xff1f; 泛型编程&#xff08;Generic Pr…

Sam Altman微软Build 2024最新演讲:AI可能是下一个移动互联网

大家好&#xff0c;我是木易&#xff0c;一个持续关注AI领域的互联网技术产品经理&#xff0c;国内Top2本科&#xff0c;美国Top10 CS研究生&#xff0c;MBA。我坚信AI是普通人变强的“外挂”&#xff0c;所以创建了“AI信息Gap”这个公众号&#xff0c;专注于分享AI全维度知识…

gfast:基于全新Go Frame 2.3+Vue3+Element Plus构建的全栈前后端分离管理系统

gfast&#xff1a;基于全新Go Frame 2.3Vue3Element Plus构建的全栈前后端分离管理系统 随着信息技术的飞速发展和数字化转型的深入&#xff0c;后台管理系统在企业信息化建设中扮演着越来越重要的角色。为了满足市场对于高效、灵活、安全后台管理系统的需求&#xff0c;gfast应…

人工智能+量子计算:飞跃现实边界还是科技幻想?

人工智能量子计算&#xff0c;这是一种可能改变世界的伙伴关系。 在科技的前沿&#xff0c;两大革命性技术——人工智能&#xff08;AI&#xff09;和量子计算——正站在合作的十字路口。人工智能&#xff0c;以其强大的数据分析能力和模式识别&#xff0c;正在改变着我们生活…

MOS选型及其参数解析

背景&#xff1a; 整理现有常用元器件选型&#xff0c;日后使用时针对性观看&#xff0c;生成列表链接如下&#xff1a; https://blog.csdn.net/caozhaokun/article/details/126069701 作者&#xff1a;Cayden 时间&#xff1a;2024/05/26 一、MOS选用现状 MOS是电路设计…

【软件设计师】面向对象技术

1.面向对象基础 1.1 基本概念 方法重载是函数名字相同&#xff0c;参数列表不同 组成 即组合&#xff0c;指整体与部分的关系&#xff0c;整体与部分生命周期相同 聚合 关联关系的一个特例&#xff0c;是体现整体与部分&#xff0c;即使has-a的关系&#xff0c;此时整体与部分…

设计模式在芯片验证中的应用——模板方法

一、模板方法 模板方法(Template Method)设计模式是一种行为设计模式&#xff0c; 它在父类中定义了一个功能的框架&#xff0c; 允许子类在不修改结构的情况下重写功能的特定步骤。也就是模板方法定义了一组有序执行的操作&#xff0c;将一些步骤的实现留给子类&#xff0c;同…

6818 android 修改开机 logo, 编译脚本分析

问题&#xff1a; 客户需要去掉 android5.1 的开机logo. 说明&#xff1a; 对于Android5.1 来说&#xff0c;uboot 与kernel 的logo 是一个。 过程&#xff1a; 其实对于开机logo 的修改很简单&#xff0c;直接参考厂家手册就可以了。 这是 android4.4 的开机logo 的修改&…

Ps:消失点滤镜 - 导出 3D 信息

Ps菜单&#xff1a;滤镜/消失点 Filter/Vanishing Point 快捷键&#xff1a;Ctrl Alt V “消失点”滤镜的导出 Export功能允许用户将创建的 3D 信息&#xff08;包括平面、纹理和测量&#xff09;导出为兼容 CAD、建模、动画和特殊效果应用程序的格式。这使得 Photoshop 与其…

上位机图像处理和嵌入式模块部署(f103 mcu和Qt上位机联动)

【 声明&#xff1a;版权所有&#xff0c;欢迎转载&#xff0c;请勿用于商业用途。 联系信箱&#xff1a;feixiaoxing 163.com】 之前我们写过一篇文章​​​​​​​&#xff0c;上面说的是如何利用串口对mcu进行控制&#xff0c;即如果利用串口实现mcu led灯的点亮和熄灭。输…

【开源】租房管理系统 JAVA+Vue+SpringBoot+MySQL

目录 一、系统介绍 租客屋主模块 房源信息模块 租客评价模块 房源订单模块 留言板模块 二、系统截图 三、核心代码 一、系统介绍 基于Vue.js和SpringBoot的租房管理系统&#xff0c;分为管理后台和用户网页端&#xff0c;可以给管理员、租客和屋主角色使用&#xff0c…

深入JVM元空间以及弹性伸缩机制

个人博客 深入JVM元空间以及弹性伸缩机制 | iwts’s blog JVM内存模型中元空间所在位置 即在JVM运行时的内存模型。总体上有这样的图&#xff1a; 元空间 上面的图其实有点不太准。方法区本质上只是JVM的一个标准&#xff0c;不同JVM在不同版本下都可能有不同的实现&#x…