linux专题:GDB详细调试方法与实现

news2024/11/23 11:30:20

系列文章目录

例如:第一章 Linux-GDB 调试实验的使用


文章目录

  • 目录

    系列文章目录

  • 文章目录

    一、实验目的

    二、实验现象

    三、实验准备 

    四、Linux GDB调试实验流程

    五、Linux GDB 调试器

    总结



一、实验目的

  1. 掌握使用 gcc 分步编译 c 代码为可执行程序步骤以及 gcc 常用选项作用
  2. 掌握 linux 系统下 gcc 编译器和 gdb 调试器的配合
  3. 掌握 Linux 系统下 gdb 调试器的使用

二、实验现象

      1.对比添加-g选项编译前面可执行程序的大小,添加-g生成的可执行程序会比较大,因为其中包括调试信息,如果要使用gdb对源码进行调试必须添加-g进行编译。

      2.对比gdb各命令的执行效果

run 重新开始运行程序,但是以前设置的断开信息不会丢失

break 可用来设置一个断开,让程序运行遇到断点停止

continue 继续全速运行程序直到遇到断点停下来

step 如果当前代码是调用一个函数,则会进入到函数源码单步运行

next 和 s 命令相似,不同点是把前代码是函数调用时,并不会进入函数源码内部单步执行

        print 可以输出变量的值

        finish 可以快速跳过当前函数

        quit 可以结束gdb 调试

三、实验准备 

  1. 系统需求:安装有 Windows 7 及以上版本的操作系统的电脑;
  2. 硬件配置:内存 4G+,硬盘 200G+,处理器 I3 以上;
  3. 软件需求:安装 VMware 虚拟机、以及在 VMware 中已经安装好Ubuntu 18.04;

四、Linux GDB调试实验流程

        1、要使用 gdb 调试器来调试程序,和编译程序时候也需要给 gcc 编译器指定编译选项才可以。本小节先通过一个简单的c 程序来学习gcc 分步编译源文件到可执行程序的分步编译方法以及常用选项。

        2、使用vim或gedit编辑器编写测试代码,具体内容如下:

@:01_gcc_test$ gedit hello.c

         编写内容如下:

#include <stdio.h> 
int main (void)
{
    printf("hello world\n") ; 
    return 0;
}

        3、gcc编译文件

gcc 指令的一般格式为:gcc [选项] 要编译的文件 [选项] [目标文件]

例:使用 gcc 编译命令,编译 hello.c 生成可执行文件 hello,并运行 hello

@:01_gcc_test$ gcc hello.c -o hello
@:01_gcc_test$ ./hello
hello world

上面的命令一步由.c 文件生成了可执行文件,将gcc 的四个编译流程:预处理、编译、汇编、连接一步完成,下面将介绍四个流程分别做了什么工作。

        4、-E 选项的作用:只进行预处理,不做其他处理。

例:只对 hello.c 文件进行预处理,生成文件 hello.i,并查看

@:01_gcc_test$ gcc -E hello.c -o hello.i 
@:01_gcc_test$ ls
hello	hello.c	hello.i

        通过查看可以看到头文件包含部分代码#include <stdio.h>经过预处理阶段之后,编译器已将 stdio.h的容贴了进来。

        5、-S 选项的使用

-S 选项的作用:只是编译不汇编,生成汇编代码

例:将 hello.i 文件只进行编译而不进行汇编,生成汇编代码 hello.s

@:01_gcc_test$ gcc -S hello.i -o hello.s 
@:01_gcc_test$ ls
hello	hello.c	hello.i	hello.s

        6、-c 选项的使用

-c 选项的作用:只是编译不连接,生成目标文件.o 

例:将汇编代码 hello.s 只编译不成 hello.o 文件

@:01_gcc_test$ gcc -c hello.s -o hello.o
 @:01_gcc_test$ ls
hello	hello.c	hello.i	hello.o	hello.s

         7、将编译好的hello.o 库,生成可执行文件hello

@:01_gcc_test$ gcc -o helloo hello.o 
@:01_gcc_test$ ./hello
hello world

        8、-static 选项的使用

-static 选项的作用:静态库

例:比较 hello.c 连接动态库生成的可执行文件 hello 和静态库生成的可执行文件 hello1 的大小默认是使用动态库链接:

@:01_gcc_test$ gcc -o hello hello.c

        添加 -static 编译时会使用静态库链接:

@:01_gcc_test$ gcc -static -o hello_static hello.c

        对比使用静态库和动态库链接的最后可执行文件大小:

@:01_gcc_test$ ls -lh hello hello_static
-rwxr-xr-x 1   8.2K 2 月	2 14:31 hello
-rwxr-xr-x 1   826K 2 月	2 14:32 hello_static

结果显示静态库的可执行文件 hello_static 比动态库的可执行文件 hello 要大的多,但是它们的执行效果是一样的。  

        9、-g 选项的使用

      -g 选项的作用:在可执行程序中包含标准调试信息

      例:将 hello.c 编译成包含标准调试信息的可执行文件 hello2

@:01_gcc_test$ gcc -g hello.c -o hello2

       对比添加-g 选项前后生成的可执行程序文件大小:

@:01_gcc_test$ ls hello hello2 -hl
-rwxr-xr-x 1   8.2K 2 月	2 14:31 hello
-rwxr-xr-x 1  	11K 2 月	2 14:35 hello2

        带有标准调试信息的可执行文件可以使用 gdb 调试器进行调试,以便找出逻辑错误。

        10、-O2 选项的使用

-O2 选项的作用:完成程序的优化工作

例:将 hello.c 用 O2 优化选项编译成可执行文件 hello3,和正常编译产生的可执行文件 hello 进行比较

@:01_gcc_test$ gcc -O2 hello.c -o hello3

五、Linux GDB 调试器

        接着上小节,本节编写一个稍微复杂一点的代码来学习 gdb 调试程序的方法,我们新创建一个新的代码目录,在新目录中编写测试代码。

        

@:01_gcc_test$ cd ..
@:syslab04$ pwd

1、先用 vim 或 gedit 编辑器编辑文件 test.c 用于 gdb 调试器调试,容如下:

       

#include <stdio.h>
int main(void) 
{
	int sum(int sum);
	int i,result=0;
	sum(100);
	for(i=1;i<=100;i++){
	result+=i;
	}
	printf("The sum in main function is %d\n",result);
	return 0;
}

int sum(int num)
 {
	int i,n=0;
	for(i=0;i<=num;i++){
	n+=i;
 }
	printf("The sum in sum function is %d\n",n);
}

2、将test.c 文件编译成包含标准调试信息的文件 test

@:02_gdb_test$ gcc -g -o test test.c    //#注意必须添加 -g 选项
@:02_gdb_test$ ls
test	test.c

3、启动gdb 进行调试

                     

@:02_gdb_test$ gdb test
GNU gdb (Ubuntu 8.1-0ubuntu3.2) 8.1.0.20180409-git Copyright (C) 2018 Free Software Foundation, Inc.
License GPLv3+: GNU GPL version 3 or later <http://gnu.org/licenses/gpl.html> This is free software: you are free to change and redistribute it.
There is NO WARRANTY, to the extent permitted by law.	Type "show copying" and "show warranty" for details.
This GDB was configured as "x86_64-linux-gnu". Type "show configuration" for configuration details. 

可以看到 gdb 启动界面中显示了 gdb 的版本、自由软件等信息,然后进入了有”gdb”开头的命令行界面

4、l(list)命令

     l 命令用于查看文件

(gdb) list
1	#include <stdio.h>
2	int main(void) 
3	{
4		int sum(int sum);
5		int i,result=0;
6		sum(100);
7		for(i=1;i<=100;i++){
8		result+=i;
9		}
10		printf("The sum in main function is %d\n",result);
(gdb) 

可以看到每行代码面前都有对应的行号,这样方便我们设置断点。

        5、b(breakpoint)命令

        b 用于设置断点,断点调试时调试程序的一个非常重要的手段,设置方法:在”b”命令之后加上对应的行号,如下:

(gdb) b 6
Breakpoint 1 at 0x400535: file a.c, line 6.
(gdb) 

6、info 命令

info break 命令用于查看断点情况,设置好断点后可以用它来查看

(gdb) info break
Num     Type           Disp Enb Address            What
1       breakpoint     keep y   0x0000000000400535 in main at a.c:6
(gdb) 

再在第 7 行增加一个断点:

(gdb) b 7
Breakpoint 2 at 0x40053f: file a.c, line 7.
(gdb) 

查看当前断点情况:

(gdb) info b
Num     Type           Disp Enb Address            What
1       breakpoint     keep y   0x0000000000400535 in main at a.c:6
2       breakpoint     keep y   0x000000000040053f in main at a.c:7
(gdb) 

7、r(run)命令

r 命令用于运行代码,默认是从首行开始运行,也可以在 r 后面加上行号,从程序中指定行开始运行。

(gdb) r
Starting program: /home/huzhiyuan/work/ddd/test 

Breakpoint 1, main () at a.c:6
6		sum(100);
(gdb) 

执行 r 命令后,可以看到程序停止在第 1 个断点处(第 6 行)。

7、c(continue)命令

当已经使用 r 命令运行程序,程序在某个断点处停止下来了,想让程序继续运行可以输入这个命令, 前面程序分别在 6,7 两行设置了两个断点,使用 r 命令程序停在第 6 行,要让程序停止在下一断点(第 7 行),输入 c 命令执行即可。

(gdb) c
Continuing.
The sum in sum function is 5050

Breakpoint 2, main () at a.c:7
7		for(i=1;i<=100;i++){
(gdb) 

可以看到程序运行到断点处就停止在第 2 个断点(第 7 行)。

8、p(print)命令

p 命令用于查看变量的值,在调试的时候我们经常要查看某个变量当前的值与我们逻辑设定的值是否

(gdb) p result
$1 = 0
(gdb) p num
$2 = num
(gdb) p i
$3 = 0
(gdb) 

9、s(step)命令

s 命令用于单步运行,另外 n(next)命令也用于单步运行,他们的区别在于:如果有函数调用的时候,

s 会进入该函数而n 不会进入该函数。

当前程序已经运行到第 7 行,现在我们也可以重启程序,让程序从头开始运行,输入 r 命令执行,然后输入 y 确认,程序会从头开始运行,直到遇到第一个断点(第 6 行)

(gdb) r
The program being debugged has been started already.
Start it from the beginning? (y or n) y
Starting program: /home/huzhiyuan/work/ddd/test 

Breakpoint 1, main () at a.c:6
6		sum(100);
(gdb) 

输入 s 命令,进入 sum 函数内部执行,如下:

(gdb) s
sum (num=100) at a.c:16
16		int i,n=0;
(gdb) 

可以看到进入了 sum 子函数,这时候就能看到 num 的值为 100。

10、n(next)命令

n 命令用于单步运行,为了测试 s 和 n 命令区别,我们重新运行程序,在第 6 行处,不使用s 命令, 而使用 n 命令测试看看结果如果,操作如下所示:

下面是 n 命令的使用:

(gdb) r
The program being debugged has been started already.
Start it from the beginning? (y or n) y
Starting program: /home/huzhiyuan/work/ddd/test 

Breakpoint 1, main () at a.c:6
6		sum(100);
(gdb) n
The sum in sum function is 5050

Breakpoint 2, main () at a.c:7
7		for(i=1;i<=100;i++){
(gdb) 

和 s 命令的运行效果对比会发现,使用 n 命令后,程序显示函数 sum 的运行结果并向下执行,而使用

s 命令后则会进入到sum 函数之中单步运行。

11、finish 命令

finish 命令用于运行程序,直到当前函数结束。例如我们进入了 sum 函数,使用 finish 命令的情况。同样,我们先重新运行程序,让程序在第 6 行停止,然后使用 s 命令进入函数内部,使用 finsh 命令快速执行完成函数代码退出函数。

(gdb) r
The program being debugged has been started already.
Start it from the beginning? (y or n) y
Starting program: /home/huzhiyuan/work/ddd/test 

Breakpoint 1, main () at a.c:6
6		sum(100);
(gdb) s
sum (num=100) at a.c:16
16		int i,n=0;
(gdb) s
17		for(i=0;i<=num;i++){
(gdb) p num
$4 = 100
(gdb) finish
Run till exit from #0  sum (num=100) at a.c:17
The sum in sum function is 5050

Breakpoint 2, main () at a.c:7
7		for(i=1;i<=100;i++){
Value returned is $5 = 32
(gdb) 

13、q(quit)命令

q 命令用于退出gdb 调试器

(gdb) q
@:02_gdb_test$

五、Linux GDB 实验原理

       使用GDB 可以调试C、C++、JAVA、汇编程序等。GDB 支持通过串口进行在线调试。

通过串口在线的调试方式,可以支持各种 CPU。调试器使用:

        1、监视程序中变量的值

        2、设置断点以使程序在指定的代码行上停止执行

        3、单步执行代码

        4、检测内存中的数据

      大多数复杂Linux 程序一样,GDB 是通过内部命令来完成调试工作的。help 命令可以例出 gdb 的命令种类,如果要看种类中的命令,可以使用 help <class> 命令,如:help breakpoints,查看设置断点的所有命令。也可以直接help <command>来查看命令的帮助。gdb 中,输入命令时,可以不用打全命令,只用打命令的前几个

字符就可以了,当然,命令的前几个字符应该要标志着一个唯一的命令

在 gdb 下,你可以敲击两次 TAB 键来补齐命令的全称,如果有重复的,那么gdb 会把其例出来。

file

装入想要调试的可执行文件.

kill

终止正在调试的程序.

list

列出产 Th 执行文件的源代码的一部分.

next

执行一行源代码但不进入函数内部.

step

执行一行源代码而且进入函数内部.

run

执行当前被调试的程序

c

继续运行程序

quit

终止 gdb

watch

使你能监视一个变量的值而不管它何时被改变.

backtrace

栈跟踪,查出代码被谁调用

print

查看变量的值

make

使你能不退出 gdb 就可以重新产Th 可执行文件.

shell

使你能不离开 gdb 就执行 UNIX shell 命令

whatis

显示变量或函数类型

break

在代码里设置断点, 这将使程序执行到这里时被挂起.

info break

显示当前断点清单,包括到达断点处的次数等。

info files

显示被调试文件的详细信息。

info func

显示所有的函数名称。

info local

显示当函数中的局部变量信息。

info prog

显示被调试程序的执行状态。

delete [n]

删除第 n 个断点

disable[n]

关闭第 n 个断点

enable[n]

开启第 n 个断点

ptype

显示结构定义

set variable

设置变量的值

call name(args)

调用并执行名为 name,参数为 args 的函数

finish

终止当前函数并输出返回值

return value

停止当前函数并返回value 给调用者


总结

       今天详细总结了GDB的操作与实现流程,欢迎关注,交流心得!!!。

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

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

【数学建模】步长的选择(优化建模)

人们每天都在行走&#xff0c;排除以运动健身为目的的走路方式&#xff0c;而仅仅考虑距离固定&#xff0c;以节省体力为最终目的的行走&#xff0c;那么选择多大的步长才最省力&#xff1f; 人在走路时所做的功等于抬高人体重心所需的势能与两腿运动所需的动能之和。在给定速度…

又到520了,来画一朵抽搐的玫瑰花吧

文章目录 静态的玫瑰 敲了这么多年代码&#xff0c;每年都得画一些心啊花啊什么的&#xff0c;所以现在常规的已经有些倦怠了&#xff0c;至少也得来个三维图形才看着比较合理&#xff0c;而且光是三维的也没啥意思&#xff0c;最好再加上能动起来。 静态的玫瑰 网上有很多生…

AIGC技术研究与应用 ---- 下一代人工智能:新范式!新生产力!(1-简介)

文章大纲 AI GC参考文献与学习路径模型进化券商研报陆奇演讲AI GC AI模型可大致分为决策式/分析式AI(Discriminant/Analytical AI)和生成式AI (Generative AI)两类。 决策式AI:学习数据中的条件概率分布,根据已有数据进行分析、判断、预测,主要应用模型有用于推荐系 统和…

Elasticsearch 集群部署插件管理及副本分片概念介绍

Elasticsearch 集群配置版本均为8以上 安装前准备 CPU 2C 内存4G或更多 操作系统: Ubuntu20.04,Ubuntu18.04,Rocky8.X,Centos 7.X 操作系统盘50G 主机名设置规则为nodeX.qingtong.org 生产环境建议准备单独的数据磁盘主机名 #各自服务器配置自己的主机名 hostnamectl set-ho…

chatgpt赋能Python-pythonf检验

Python的重要性与应用 Python是一种高级编程语言&#xff0c;因其简单易学和灵活性而备受欢迎。它已经成为数据分析、web开发、机器学习等许多领域的重要工具。在本篇文章中&#xff0c;我们将探讨Python在SEO中的作用。 Python对SEO的影响 SEO是搜索引擎优化的缩写&#xf…

【数据结构】线性表 ⑥ ( 双循环链表 | 双循环链表插入操作 | 双循环链表删除操作 | LinkedList 双循环链表源码分析 )

文章目录 一、双循环链表插入操作处理二、双循环链表删除操作处理三、LinkedList 双循环链表源码分析1、链表节点2、LinkedList 链表中收尾元素指针3、链表插入操作4、链表向指定位置插入操作5、获取指定索引的元素6、删除指定索引的元素 一、双循环链表插入操作处理 双循环链表…

【JVM】6. 堆

文章目录 6.1. 堆&#xff08;Heap&#xff09;的核心概述6.1.1. 堆内存细分6.1.2. 堆空间内部结构&#xff08;JDK7&#xff09;6.1.3. 堆空间内部结构&#xff08;JDK8&#xff09; 6.2. 设置堆内存大小与OOM6.2.1. 堆空间大小的设置6.2.2. OutOfMemory举例 6.3. 年轻代与老年…

[CTF/网络安全] 攻防世界 backup 解题详析

[CTF/网络安全] 攻防世界 backup 解题详析 PHP备份文件名备份文件漏洞成因备份文件名常用后缀姿势总结 题目描述&#xff1a;X老师忘记删除备份文件&#xff0c;他派小宁同学去把备份文件找出来,一起来帮小宁同学吧&#xff01; PHP备份文件名 PHP 脚本文件的备份文件名&#…

【瑞萨RA_FSP】外部中断

文章目录 一、外部引脚中断二、中断过程三、按键外部中断 一、外部引脚中断 1. ICU框图 根据ICU的功能框图可以知道&#xff0c;首先需要配置IRQCR寄存器(IRQ Control Register&#xff0c;IRQ英文全称&#xff1a;Interrupt ReQuest&#xff0c;中文名&#xff1a;中断请求&a…

C++入门篇---(命名空间、缺省参数、以及输入、输出)

前言 c 我来了,恭喜牛牛解锁新世界.开启c的学习之旅. &#x1f388;个人主页:&#x1f388; :✨✨✨初阶牛✨✨✨ &#x1f43b;推荐专栏: &#x1f354;&#x1f35f;&#x1f32f;C语言进阶 &#x1f511;个人信条: &#x1f335;知行合一 &#x1f349;本篇简介:>:讲解C…

30年后,茶产业规模是现在的10倍

做个预言&#xff1a;30年后&#xff0c;茶产业是现在的10倍 【5.21是世界茶日】 杭州中国茶博会&#xff0c;我来啦 人工智能越让生产效率越来越高 常用物质将会唾手可得 人闲着&#xff0c;无法体会活着的意义&#xff0c;才是挑战 田园诗茶生活方式会有一席之地 趣讲大白话&…

【EMC专题】案例:读一读TI的按接口选择ESD器件指南

在TI的官网上看到一份ESD by Interface Selection Guide,也就是按接口选择ESD器件指南。因此想读一读看看一起学习一下。 首先看一下文档,是比较简明的。可以看到不同的接口推荐了一些不同的保护器件。因为应用环境不一样,所有有不同的器件封装(如单体、集成TVS等),这样在…

Spyder可在线使用!?

不同安装&#xff0c;如果想使用spyder进行编程&#xff0c;可以用其在线版&#xff0c;和本地版功能一样&#xff0c;就是有点慢。 另外需要用chrome浏览器&#xff0c;用火狐没法正常访问。 Spyder可以在线使用&#xff0c;所以在没有安装python环境的电脑上&#xff0c;想…

Linux常用命令——hostname命令

在线Linux命令查询工具 hostname 显示和设置系统的主机名 补充说明 hostname命令用于显示和设置系统的主机名称。环境变量HOSTNAME也保存了当前的主机名。在使用hostname命令设置主机名后&#xff0c;系统并不会永久保存新的主机名&#xff0c;重新启动机器之后还是原来的主…

字符串匹配--BF算法和KMP算法

0.前言 字符串函数strstr相信大家都不陌生–就是在一个字符串&#xff08;主串&#xff09;中找查找另一个字符串&#xff08;子串&#xff09;&#xff0c;并返回子串在主串中的位置。那么这个函数是怎么实现的呢&#xff1f;这就涉及字符串匹配的问题&#xff0c;本章就让我们…

Node.js 事件循环和事件派发器

目录 1、process.nextTick() 介绍 2、setTimeout() 3、零延迟 4、setInterval() 5、递归setTimeout 6、setImmediate() 7、Node.js 事件派发器 1、process.nextTick() 介绍 Node.js中 process.nextTick函数以一种特殊的方式与事件循环交互。 当你试图理解Node.js事件循…

Redis数据结构——QuickList、SkipList、RedisObjective

承接上文&#xff0c;本文主要介绍QuickList、SkipList、RedisObjective 四、 Redis数据结构-QuickList 问题1&#xff1a;ZipList虽然节省内存&#xff0c;但申请内存必须是连续空间&#xff0c;如果内存占用较多&#xff0c;申请内存效率很低。怎么办&#xff1f; ​ 答&a…

计算机操作系统(慕课版)第二章课后题答案

一、简答题 (1)什么是前趋图&#xff1f;试画出下面四条语句的前趋图. S1&#xff1a;axy&#xff1b; S2&#xff1a;bz1&#xff1b; S3&#xff1a;ca-b&#xff1b; S4&#xff1a;wc1&#xff1b; 答&#xff1a;前趋图(Precedence Graph)是一个有向无循环图&#xff0c;…

chatgpt赋能Python-pythondataframe取出一列

用 Python Dataframe 取出一列 数据分析中&#xff0c;用到的数据往往是有多列多行的。而在实际的分析过程中&#xff0c;我们需要针对其中的某一列进行处理。这个时候&#xff0c;Python中的Dataframe就成了我们的利器。 在这篇文章中&#xff0c;我们将教你如何使用Python …

chatgpt赋能Python-pythongit

PythonGit&#xff1a;使Git操作更加高效 Git作为目前最流行的版本控制工具之一&#xff0c;已经被广泛应用于软件开发、Web开发等领域。PythonGit则是一个基于Python编写的Git客户端库&#xff0c;可以让开发者们更加高效地进行Git操作&#xff0c;提高开发效率。 PythonGit…