【Linux】编译器gcc和g++与调试器gdb的使用

news2024/11/28 19:34:47

文章目录

  • 一、Linux编译器-gcc/g++
    • 1.程序运行的四个阶段
      • 1.1 预处理
      • 1.2 编译
      • 1.3 汇编
      • 1.4 链接
    • 2.链接方式与函数库
      • 2.1 动态链接与静态链接
      • 2.2 动态库与静态库
      • 3.gcc/g++的使用
  • 二、Linux调试器--gdb
    • 1.debug与release
    • 2.gdb 的使用

一、Linux编译器-gcc/g++

1.程序运行的四个阶段

我们知道,一个程序被运行起来之后需要经历四个阶段然后才变成一个可执行的程序,他们分别为:预处理,编译,汇编和链接。下面我们将介绍这四个阶段的操作,测试代码如下:

#include <stdio.h>
// 宏定义
#define N 10

int main()
{
	// 测试注释
	// printf("hello 1\n");
	// printf("hello 2\n");
	// printf("hello 3\n");
	// printf("hello 4\n");
	printf("hello 5\n");
	printf("hello 6\n");
	printf("hello 7\n");
	printf("hello 8\n");
	printf("hello 9\n");
	printf("hello 10\n");

	// 测试宏
	printf("%d\n", N);

	// 测试条件编译
#ifdef SHOW
	printf("hello SHOW\n");
#else
	printf("hello DEFAULT\n");
#endif

	return 0;
}

1.1 预处理

预处理也叫预编译,程序在预处理阶段会完成如下操作:

展开头文件,将头文件中的代码拷贝到当前代码中

删除注释

执行条件编译

完成#define定义的符号,宏的替换以及删除

在Linux下我们可以通过如下指令就可以得到经过预处理之后的代码

gcc -E test.c -o test.i

gcc : 表示使用gcc编译器来编译该代码

-E :表示让代码完成预处理之后就停下来

test.c : 我们要编译的代码

test.i:预处理产生的文件一般以.i为后缀

-o test.i :用于指明临时文件的名称(test.i),经过预处理之后它会形成一个名称为test.i的临时文件,而不是输出到终端上

在这里插入图片描述

在这里插入图片描述

我们可以看到,经过预处理之后,头文件stdio.h中的内容全部会被拷贝到test.i中,所以test.i一个有800多行,我们注释的内容也全部被删除,宏定义被替换,条件编译被执行

1.2 编译

程序在编译阶段会完成如下操作:

语法分析

词法分析

语义分析

符号汇总

我们通过如下指令来获取程序编译之后的代码:

gcc -S test.i -o test.s

-s:表示让代码在完成编译之后停下来,不再继续之后后面的过程

编译产生的文件一般以.s为后缀

在这里插入图片描述

在这里插入图片描述

我们可以看到,编译阶段会将高级语言转换成汇编语言

1.3 汇编

汇编阶段会将编译阶段生成的汇编代码转换成计算机可以识别的二进制目标代码,其中生成的.o文件被称为可重定向的二进制目标文件

我们通过如下指令来获取程序汇编之后的代码:

gcc -c test.o -o test.s

-c:表示让代码在完成汇编之后停下来,不再继续往后执行

汇编产生的文件一般以.s为后缀

在这里插入图片描述

在这里插入图片描述

这样我们就得到了二进制目标文件,但我们使用一般的文本编辑器打开发现是一堆我们看不见的符号,我们可以通过如下指令以指定的格式打开它(默认是八进制):

od test.o

在这里插入图片描述

1.4 链接

程序在链接的过程中会完成如下操作:

1.合并段表,编译器会把汇编阶段生成的多个文件中相同格式的数据合并到一起,最终形成一个.exe文件

2.符号表的合并和重定位,符号表的合并是编译器会把在汇编阶段生成的多个符号表合成一个符号表,重定位是当同一个符号出现在两个符号表中时,编译器会选取其中一个有效的地址相关的一个,舍弃另外一个

在Linux中,链接我们直接使用gcc即可,如果我们没有指定将生成的临时文件的话,默认会将结果存放在a.out中

gcc test.o //默认
gcc test.c -o test.out // 保存到test.out文件中

在这里插入图片描述

在这里插入图片描述

我们最后通过链接得到的文件称为可执行程序,它里面保存的也是计算机能够识别的二进制指令

我们两个文件都可以输出最终的结果:

在这里插入图片描述

虽然我们将gcc编译代码分为预处理,编译,汇编和链接,但是我们在日常生活中运行代码时,直接使用"gcc test.c -o test.out"或者"gcc test.c"即可,这里分为四个阶段是为了让我们更好的理解程序的运行过程

2.链接方式与函数库

2.1 动态链接与静态链接

我们的C程序中,并没有定义“printf”的函数实现,且在预编译中包含的“stdio.h”中也只有该函数的声明,而没有定义函数的实现,那么,是在哪里实现“printf”函数的呢?

最后的答案是:系统把这些函数实现都被做到名为 libc.so.6 的库文件中去了,在没有特别指定时,gcc 会到系统默认的搜索路径“/usr/lib”下进行查找,也就是链接到 libc.so.6 库函数中去,这样就能实现函数“printf”了,而这也就是链接的作用

这是因为我们在编写代码的时候,除了自己实现的函数外,比如printf函数我们会去调用函数库中的代码,但是stdio.h里只有函数的声明,没有函数的实现。此外,程序在预处理,编译和汇编阶段处理的都是我们自己的代码,只有在链接的时候,库函数的实现才会和我们的代码关联起来(符号表的重定位),所以,链接的本质是我们在调用库函数的时候如何与标准库相关联的问题,程序一共有两种链接方式:动态链接和静态链接

动态链接

动态链接是指执行代码的时候,如果遇到库函数调用就跳转到动态库中对应的函数的定义的地方,然后执行该函数,执行完毕后再跳转到原程序处然后继续往后执行,它的优点就是形成的可执行程序小,缺点是受动态库变动(删除,升级等)的影响

静态链接

静态链接是直接将程序需要使用的库函数都从对应的静态库中拷贝一份到原程序中,它的优点是不受静态库(删除,升级等)的影响,缺点是形成的可执行程序大

2.2 动态库与静态库

函数库是一些事先写好的,用于给别人使用的函数的集合,函数库分为静态库和动态库

静态库

静态库是指编译链接时,把库文件的代码全部加入到可执行文件中,因此生成的文件比较大,但在运行时也就不再需要库文件了。在Linux在其后缀名一般为“.a“,在windows在的后缀名为”.lib“

动态库

动态库与之相反,在编译链接时并没有把库文件的代码加入到可执行文件中,而是在程序执行时由运行时链接文件加载库,这样可以节省系统的开销。在Linux下动态库一般后缀名为“.so”,在windows下其后缀名为“.dll”

【注意】

1.动态链接必须使用动态库,静态链接必须使用静态库,即进行动态链接时只能跳转到动态库中对应的函数实现处,进行静态链接时只能拷贝静态库中的函数实现

2.gcc 在编译时默认使用动态库。完成了链接之后,gcc 就可以生成可执行文件,gcc默认生成的二进制程序,是动态链接的.原因如下:

  • 如果使用静态链接,那么程序形成的可执行程序大,此时,不仅仅占用磁盘的空间大,其被运行时加载到内存所占用的空间也会很大,而我们的内容有限,运行过大的程序可能会导致卡死无法运行
  • 虽然动态链接受库函数变动的影响,但是库函数一般是很少变动的,即使变动也会兼容以前的版本,所以对程序的影响不大
  • 在Linux下,我们可以使用"file"指令来辨别文件的类型,使用"ldd"来打印或查看程序运行所 需要的共享库

在这里插入图片描述

Linux一般会自动安装C语言动态库,因为Linux下的大多数指令以及我们默认使用的gcc编译得到的可执行程序都是动态链接的,依赖于C动态库,但是C静态库,C++静态库可能就需要我们自己进行安装。我们可以使用如下命令来安装C和C++的静态库:

sudo yum install -y glibc-static
sudo yum install -y libstdc++-static

我们可以使用"-static"选项来指定程序使用静态方式进行链接:

在这里插入图片描述

我们可以看到,使用静态链接方式形成的可执行程序比动态链接方式形成的可执行程序的要大100倍左右,即一个动态链接只有1M的文件,使用静态链接方式形成的可执行程序就有几百M,两者之间相差非常大,所以Linux默认使用静态链接的方式

3.gcc/g++的使用

在Linux在,我们可以使用如下指令来安装gcc和g++:

sudo yum install -y gcc
sudo yum install -y gcc-g++ libstdc++-devel

gcc与g++的使用如下:

-E 只激活预处理,在完成预处理后停下来,不再往后继续执行,生成以.i为后缀的文件

-S 在完成编译后停下来,不再继续往后执行,生成的文件以.o为后缀 编译到汇编语言不进行汇编和链接

-c 在完成汇编之后停下来,不再继续往后执行,生成以.o为后缀的文件 编译到目标代码

-o 将输出到终端的内容保存到指定的文件中

-static 此选项对生成的文件采用静态链接

-g 以debug的方式发布软件,生成调试信息。GNU 调试器可利用该信息。

-shared 此选项将尽量使用动态库,所以生成文件比较小,但是需要系统由动态库.

-O0-O1-O2-O3 编译器的优化选项的4个级别

-O0表示没有优化,这是默认的编译选项

-O1为缺省值,编译器会在不花费太多编译时间的同时试图生成更快更小的代码。这些优化是非常基础的,但一般这些任务肯定能顺利完成

-O2 -O2会比-O1启用多一些标记。设置了-O2后,编译器会试图提高代码性能而不会增大体积和大量占用的编译时间

-O3优化级别最高 在O2的基础上进行更多的优化,用这个选项会延长编译代码的时间,并且在使用gcc4.x的系统里不应全局启用

-w 不生成任何警告信息。

-Wall 生成所有警告信息。

二、Linux调试器–gdb

1.debug与release

在windows中使用VS的时候我们知道,程序的发布方式一共有两种-debug模式和release模式,其中debug模式是给程序员使用的,其中包含调试的各种信息,程序员可以根据这些调试信息对程序进行修改和完善,而release模式则是给用户使用的,它不包含调试信息,因为用户不负责也不关心对程序进行调试。

Linux gcc/g++出来的二进制程序,默认是release模式,如果我们要使用gdb调试,必须在源代码生成二进制程序的时候, 加上 -g 选项,标识以debug方式发布

#include <stdio.h>
#include <time.h>

int AddToVal(int from,int to)
{
    int sum=0;
    int i=0;
    for(i=from;i<=to;++i)                                                                     {
        sum+=i;
    }
    return sum;
}
void Print(int sum)
{
    long long timestamp=time(NULL);
    printf("result=%d,timestamp:%lld\n",sum,timestamp);
}
int main()
{
    int sum=AddToVal(0,100);
    Print(sum);
    return 0;
}

在这里插入图片描述

在这里插入图片描述

我们可以发现,以debug方式发布的和以release方式发布的程序无论是在大小,程序内部的包含的相关的调试信息,还是debug模式下是否具有调试样例都是由明显区别的

2.gdb 的使用

当我们使用-g选项的时候就可以得到以debug模式发布的可执行程序,然后我们就可以使用gdb对其进行调试了:

gdb的安装

在Linux在,我们可以使用如下指令来安装gdb:

sudo yum install -y gdb

gdb调试的常见选项如下:

list/l 行号:显示binFile源代码,接着上次的位置往下列,每次列10行。我们第一次使用l显示源代码后,我们下一次再使用l或者下一次使用enter时,它会接着上一次的位置接着向下显示

list/l 函数名:列出某个函数的源代码。

r或run:运行程序。调试运行,如果程序中有断点,则在断点处停下来,如果没有,则直接 将程序执行完毕,相当于VS中的F5

n 或 next:单条执行。逐过程调试,相当于VS的F10

s或step:进入函数调用 逐语句调试,相当于VS的F11

break(b) 行号:在某一行设置断点,相当于VS的F9

break 函数名:在某个函数开头设置断点

info break :查看断点信息。

finish:执行到当前函数返回,然后停下来等待命令 把当前函数执行完毕

print§:打印表达式的值,通过表达式可以修改变量的值或者调用函数

p 变量:打印变量值。

set var:修改变量的值

continue(或c):从当前位置开始连续而非单步执行程序 运行至下一个断点处停下来,如果断点所在行不是一条语句,比如"{" “}” 或者空行,那么它会继续往后继续执行到有效行处

run(或r):从开始连续而非单步执行程序

delete breakpoints:删除所有断点

delete breakpoints n:删除序号为n的断点 (d 断点编号),每个断点都有自己的编号,我们删除断点时需要指明对应的断点编号

disable breakpoints:禁用断点

enable breakpoints:启用断点

info(或i) breakpoints:参看当前设置了哪些断点

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

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

until X行号:跳至X行

breaktrace(或bt):查看各级函数调用及参数

info(i) locals:查看当前栈帧局部变量的值

quit:退出gdb

我们重点掌握下面的即可:

在这里插入图片描述

指令演示

l行号显示源代码

在这里插入图片描述

l 函数显示该函数的源代码

在这里插入图片描述

r 运行程序

在这里插入图片描述

b 行号打断点,info b查看断点,d 断点编号 删除断点

在这里插入图片描述

r 调试运行

在这里插入图片描述

n 逐过程调试,s逐语句调试

在这里插入图片描述

c 运行至下一个断点处停下

在这里插入图片描述

bt 查看调用堆栈

在这里插入图片描述

p 变量,查看变量值,display 跟踪查看变量 undisplay取消跟踪

在这里插入图片描述

finish 把当前函数运行完,q 退出gdb1

在这里插入图片描述

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

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

相关文章

RK3588-EDGE Ethernet驱动(一)

一:概述 以太网从硬件层来讲大致可分为三部分:CPU,MAC,PHY。 上述三部分有以下几种组成方式,而非封装在一颗IC种。 CPU内部集成了MAC和PHY,难度较高CPU内部集成MAC,PHY采用独立芯片(主流方案)CPU不集成MAC和PHY,MAC和PHY采用独立芯片或者集成芯片(高端采用)其中常说的…

MetaHuman结合第三人称角色,增加走路跑步动画

一、准备第三人称角色资源 1.新建工程选择第三人称角色,将第三人称角色拷贝到MetaHumans目录下 2.复制一个数字人,父类指定为BPThirdPersonCharacter 3.将Body移动到Mesh下边 调整好姿势和位置 4.可以将头发的UseCards设置为true,可以减少性能消耗 5.编译报错修复

【 网络常见的 9 大命令,非常实用!】

网络常见的 9 大命令&#xff0c;非常实用&#xff01; 1&#xff0e;ping 命令 PING &#xff08;Packet Internet Groper&#xff09;&#xff0c; 因特网包探索器&#xff0c;用于测试网络连接量的程序 。Ping是工作在 TCP/IP网络体系结构中应用层的一个服务命令&#xff…

随机网络构建

随机网络构建 文章目录 随机网络构建[toc]1 随机网络定义2 网络拓扑性质2.1 边数分布2.2 度分布 3 代码实现 1 随机网络定义 随机网络与规则网络相对应&#xff0c;最为经典的随机网络模型是Erds和Rnyi研究的ER随机图模型&#xff0c;ER随机图模型有两种定义方式&#xff1a; …

(2020,ADA)用有限的数据训练生成对抗网络

Training generative adversarial networks with limited data 公众号&#xff1a;EDPJ 目录 0. 摘要 1. 简介 2. GAN 中的过度拟合 2.1 随机鉴别器增强&#xff08;stochastic discriminator augmentation&#xff09; 2.2 设计不泄漏的增强 2.3 我们的增强流程 3. 自…

阿里云轻量服务器--Docker--RocketMq安装

前言&#xff1a;本文介绍使用docker 部署-RocketMq&#xff1b; 1 RocketMq 介绍&#xff1a; Apache RocketMQ是一款开源的分布式消息中间件&#xff0c;具有高吞吐量、高可用性、高伸缩性和灵活的可靠消息传输机制等特点。RocketMQ支持多种消息模式&#xff0c;包括异步传…

【App自动化测试】(十八)多设备管理平台——openSTF

目录 1. openSTF2. openSTF的安装部署2.1 MacOS2.2 Windows 3. STF操作3.1 基础操作——远程调试虚拟设备3.2 高阶操作——远程调试真机 1. openSTF OpenSTF&#xff1a;是一个手机设备管理平台&#xff0c;可以对手机进行远程管理、调试、远程手机桌面监控等操作。 特点&…

有关深度学习打标签DIY的五种方式

有关深度学习打标签DIY的五种方式&#xff1a;Labelme、LabelImg、EISeg、Make Sence和CVat等 五种制作Label的方式&#xff1a;1.CVAT&#xff08;Open Data Annotation Platform&#xff09;2.EISeg&#xff08;Efficient Interactive Segmentation&#xff09;自动标注3.Mak…

中国人民大学与加拿大女王金融硕士国际班——全方位培养金融人才,你心动了吗

中国人民大学与加拿大女王大学中外合作办学的金融硕士项目有国际班&#xff08;使用英文授课&#xff0c;无工作经验要求&#xff09;和高管班&#xff08;使用中文授课&#xff0c;一般需在中国金融行业拥有至少7年以上的工作经验&#xff09;两个班次&#xff0c;属于滚动式录…

机器学习模型——分类模型

文章目录 K近邻&#xff08;KNN&#xff09;KNN示例KNN距离计算KNN算法代码实现1. 引入依赖&#xff1a;2. 数据加载和预处理&#xff1a;3. 核心算法实现&#xff1a;4. 测试&#xff1a; 逻辑斯谛回归线性回归问题分类边界曲线——逻辑斯谛回归Sigmoid函数&#xff08;压缩函…

多模块更新,助力模型训练及应用|ModelWhale 版本更新

绿暗红稀&#xff0c;蝉鸣草长。本次更新中&#xff0c;ModelWhale 带来了一系列的功能优化&#xff0c;期待为你提供更好的使用体验。 本次更新中&#xff0c;ModelWhale 主要进行了以下功能迭代&#xff1a; • 优化 模型与人工组合式数据标注&#xff08;团队版✓ &#xf…

基于stm32F407的hal库,移植FreeRTOS的具体步骤和遇到的问题(看正点原子的视频)

1. 资料准备 因为板子是stm32F407的第二版的&#xff0c;所以开始下的资料是旧版本的&#xff0c;但是旧版本的FreeRTOS工程没有hal库的&#xff0c;都是标准库的&#xff0c;这里是下载stm32F407最新版的资料&#xff0c;进行移植。 资料可以在正点原子官网下载&#xff0c;…

格式化输出Printf总结说明

一&#xff0c;简介 在C语言运行调试过程中&#xff0c;需要使用printf进行打印log信息&#xff0c;本文主要介绍常用的printf打印格式信息&#xff0c;方便提高调试的效率。 二&#xff0c;Printf转换说明 printf函数的转换说明由字符%和跟随其后的最多5个不同的选项构成&a…

PHP快速实战18-PHP使用PHPMailer来发送邮件

文章目录 前言安裝与实现步骤1&#xff1a;下载PHPMailer步骤2&#xff1a;包含PHPMailer文件步骤3&#xff1a;设置SMTP服务器和端口号步骤4&#xff1a;设置发件人和收件人步骤5&#xff1a;设置邮件主题和内容步骤6&#xff1a;添加附件&#xff08;可选&#xff09;步骤7&a…

深度学习-第T8周——猫狗识别

深度学习-第T8周——猫狗识别 深度学习-第T8周——猫狗识别一、前言二、我的环境三、前期工作1、导入数据集2、查看图片数目 四、数据预处理1、 加载数据1.1、设置图片格式1.2、划分训练集1.3、划分验证集1.4、查看标签1.5、再次检查数据1.6、配置数据集 2、数据可视化 五、搭建…

GMesh网格选项介绍

GMesh网格介绍 2D mesh algorithm MeshAdapt&#xff1a;这是一种自适应网格算法&#xff0c;可在需要更大的精度或在某些区域需要更密集的网格时自动添加额外的网格。该算法的优点包括较高的收敛性和灵活性&#xff0c;它可以让用户在需要的地方添加更多的网格&#xff0c;但…

隐形黑客潜入美国和关岛关键基础设施而未被发现

微软和“五眼联盟”国家周三表示&#xff0c;一个隐秘的组织成功地在美国和关岛的关键基础设施组织中建立了一个持久的立足点&#xff0c;而没有被发现。 这家科技巨头的威胁情报团队正在以伏特台风(Volt Typhoon)的名义跟踪这些活动&#xff0c;包括入侵后的凭证访问和网络系…

如何实现torna文档生成管理工具api接口从内网到外网的访问?

企业接口文档解决方案&#xff0c;目标是让文档管理变得更加方便、快捷。Torna采用团队协作的方式管理和维护项目API文档&#xff0c;将不同形式的文档纳入进来&#xff0c;形成一个统一的维护方式。下面简单给大家介绍一下torna接口文档管理工具都有哪些功能特性&#xff1a; …

【Java EE 初阶】TCP协议的安全效率机制

目录 1.应用层协议 2.传输层协议 3.UDP协议格式 4.TCP协议格式 5.TCP的安全效率机制 1.确认应答机制 2.超时重传机制 但是&#xff0c;主机A未收到B发来的确认应答&#xff0c;也可能是因为ACK丢失了&#xff1b; 3.连接管理机制 面试题&#xff1a;会不会有可能变成三…

【A卡,Windows】stable diffusion webui下载安装避坑指南

观前提醒 本文内容都是本人亲身经历的&#xff0c;一个一个安装下载测试所感&#xff0c;当然如果你更想用傻瓜式集成包的&#xff0c;那还是跳过这篇文章吧。 当然我不推荐这篇文章的操作&#xff0c;因为我用了差不多1h才有一副图&#xff0c;有N卡&#xff0c;就用N卡&…