【Linux】--- Linux编译器-gcc/g++、调试器-gdb、项目自动化构建工具-make/Makefile 使用

news2024/11/19 14:46:57

目录

  • 一、Linux编译器-gcc/g++
    • 1.1 gcc/g++ 使用方法
    • 1.2 程序的翻译过程
    • 1.3 链接 -- 动静态链接特点及区别
  • 二、Linux调试器-gdb
    • 2.1 背景
    • 2.2 使用方法
  • 三、Linux项目自动化构建工具-make/Makefile
    • 3.1 背景
    • 3.2 原理
    • 3.3 项目清理

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

1.1 gcc/g++ 使用方法

格式: gcc [选项] 要编译的文件 [选项] [目标文件]gcc / g++安装: sudo yum install -y gcc-c++。安装后的编译器默认的版本是较低的,我们可以使用选项-std=c99(即使用c99标准),-std=c++11(即使用c++11的标准)来进行版本提升。使用-o选项,可以将编译生成的可执行重命名。最后使用./可执行,来运行程序。如下:

在这里插入图片描述

Linux中一个文件要真正的执行:1. 有x权限;2. 就是一个可执行文件。 很明显文件test.exe满足上述条件!

1.2 程序的翻译过程

程序的翻译过程,可以说是生成二进制方案的过程,具体可以细分为以下几步:

  • 预处理:

预处理功能主要包括宏定义,文件包含,条件编译,去注释等。 预处理指令是以#号开头的代码行。

实例: gcc -E test.c -o test.i。选项"-E",该选项的作用是让gcc从现在开始进行程序的翻译,预处理完成就停下! 选项"-o"是指目标文件,".i"文件为已经过预处理的C原始程序。

  • 编译(生成汇编):

在这个阶段中,gcc 首先要检查代码的规范性、是否有语法错误等,以确定代码的实际要做的工作,在检查无误后,gcc把c语言代码翻译成汇编语言。

实例: gcc -S test.i -o test.s。用户可以使用"-S"选项来进行查看,该选项的作用是让gcc从现在开始进行程序的翻译,编译完成就停下! 可以从test.c开始编译,也可以从test.i开始。

  • 汇编(生成机器可识别代码):

汇编阶段是把编译阶段生成的".s"文件转成目标文件(即将汇编语言编译成为,二进制目标文件

实例: gcc -c test.s -o test.o。读者在此可使用选项"-c",该选项的作用是让gcc从现在开始进行程序的翻译,汇编完成就停下!。就可看到汇编代码已转化为".o"的二进制目标代码了。

  • 链接(生成可执行文件或库文件):

实例: gcc hello.o –o hello。在成功编译之后,就进入了链接阶段,最后形成可执行程序


那么为什么会有这些过程呢?

这就要说到编程语言的历史了。最初的计算机只能处理二进制,二进制是处理器的“母语”。这叫“机器语言”或者“机器码”。在计算机早期阶段,必须用机器码写程序(即二进制编程)(前段时间很火的《三体1》中,早期叶文洁当时就是使用的二进制编程,还用到了打孔带,上面记录的就是二进制信息)。

在1940-1950年代,程序员开发一种新语言(汇编语言),它为每个操作码分配一个简单名字,叫“助记符”,助记符后面紧跟数据,形成完整指令。当然,计算机并不认识助记符,它只认得二进制码,然后就有了汇编的编译器,它可以读懂文字指令,自动转换成二进制指令,这种程序叫“汇编器”

汇编语言直接对应机器码,虽然已经很方便了。但是,汇编器仍然强迫程序员思考,用什么寄存器和内存地址,如果我们突然要用额外一个数,可能要改很多代码。这时候就出现了一些高级语言和与之对应的编译器(如:C,C++,Java…)。

因为计算机只认识二进制。以c语言为例,所以我们要先将c语言代码转化为汇编代码,然后再转为二进制目标文件。 那为什么不直接将c语言转为二进制目标文件呢?因为前人已经写好了汇编的编译器,我们只需站在巨人的肩膀上,再将高级语言转为较简单的汇编代码即可。

那么如何形成第一个汇编写的汇编编译器呢?

在这里插入图片描述
先用二进制写一个汇编编译器(此时汇编代码便可通过此编译器形成软件)。汇编编译器本质上就是软件,那么便可先用汇编语言写一个新的编译器,再将这个新的编译器放在二进制写的汇编编译器上执行,最后形成新的汇编编译器(软件)。日后只需维护汇编代码即可! 这个过程也可叫做编译器的自举(bootstrap),c语言的第一个编译器也是如此形成的!

1.3 链接 – 动静态链接特点及区别

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

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

函数库一般分为静态库和动态库两种。

  • 静态库是指编译链接时,把库文件的代码全部加入到可执行文件中,因此生成的文件比较大,但在运行时也就不再需要库文件了。其后缀名一般为".a"
  • 动态库与之相反,在编译链接时并没有把库文件的代码加入到可执行文件中,而是在程序执行时由运行时链接文件加载库,这样可以节省系统的开销。动态库一般后缀名为".so",如前面所述的 libc.so.6就是动态库。gcc在编译时默认使用动态库。完成了链接之后,gcc就可以生成可执行文件,如下所示。 gcc test.o –o test
  • gcc默认生成的二进制程序,是动态链接的,这点可以通过 file命令验证。

验证:

  1. -static指令,作用是链接时使用静态链接:

在这里插入图片描述
2. ldd 可执行指令,作用是查看链接的库:

在这里插入图片描述

  1. file filename指令,查看链接属性:

在这里插入图片描述


动态库 && 动态链接的优缺点:1. 不能丢失。共享动态库,但是一旦动态库缺失,所有的动态链接这个库的程序,都无法执行! 2. 节省资源。

静态库 && 静态链接的优缺点:1. 一旦形成,与库无关。在编译的时候,把库中的方法,拷贝到我自己的可执行程序中,此时程序将不再关心任何的库; 2. 浪费资源,占用空间大。

二、Linux调试器-gdb

2.1 背景

程序的发布方式有两种,debug模式和release模式。Linux gcc/g++出来的二进制程序,默认是release模式。 要使用gdb调试,必须在源代码生成二进制程序的时候,加上 -g选项,此时编译器形成可执行程序的时候,会给可执行程序添加调试信息。 我们也可以发现可调式的可执行程序比普通的程序占用内存大。

在这里插入图片描述

调试信息大致如下:

在这里插入图片描述

2.2 使用方法

gdb binFile退出: ctrl + dquit调试命令:

  • list/l 行号: 显示binFile源代码,接着上次的位置往下列,每次列10行。
  • list/l 函数名: 列出某个函数的源代码。
  • r或run: 运行程序(对比VS F5)。
  • n 或 next: 单条执行,逐过程(对比VS F10)。
  • s或step: 进入函数调用,逐语句(对比VS F11)。
  • break(b) 行号: 在某一行设置断点。
  • break 函数名: 在某个函数开头设置断点。
  • info break : 查看断点信息。
  • finish: 执行到当前函数返回,然后停下来等待命令。
  • print(): 打印表达式的值,通过表达式可以修改变量的值或者调用函数。
  • p 变量: 打印变量值。
  • set var: 修改变量的值。
  • continue(或c): 从当前位置开始连续而非单步执行程序。
  • delete breakpoints(b): 删除所有断点。
  • delete breakpoints((b) n: 删除序号为n的断点。
  • disable breakpoints(b): 禁用断点。
  • enable breakpoints(b): 启用断点。
  • info(或i) breakpoints(b): 参看当前设置了哪些断点。
  • display 变量名: 跟踪查看一个变量,每次停下来都显示它的值。
  • undisplay: 取消对先前设置的那些变量的跟踪。
  • until X行号: 跳至X行。
  • breaktrace(或bt): 查看各级函数调用及参数。
  • info(i) locals: 查看当前栈帧局部变量的值。
  • quit: 退出gdb。

三、Linux项目自动化构建工具-make/Makefile

3.1 背景

  • 会不会写makefile,从一个侧面说明了一个人是否具备完成大型工程的能力;
  • 一个工程中的源文件不计数,其按类型、功能、模块分别放在若干个目录中,makefile定义了一系列的规则来指定,哪些文件需要先编译,哪些文件需要后编译,哪些文件需要重新编译,甚至于进行更复杂的功能操作;
  • makefile带来的好处就是——“自动化编译”,一旦写好,只需要一个make命令,整个工程完全自动编译,极大的提高了软件开发的效率;
  • make是一个命令工具,是一个解释makefile中指令的命令工具,一般来说,大多数的IDE都有这个命令,比如:DelphimakeVisual C++nmakeLinuxGNUmake。可见,makefile都成为了一种在工程方面的编译方法;
  • make是一条命令,makefile是一个文件,两个搭配使用,完成项目自动化构建。

3.2 原理

make是如何工作的,在默认的方式下,也就是我们只输入make命令。那么,

  1. make在当前目录下找名字叫"Makefile""makefile"的文件。
  2. 如果找到,它会找文件中的第一个目标文件(target),在上面的例子中,他会找到"code.exe"这个文件,并把这个文件作为最终的目标文件。
  3. 如果code.exe文件不存在,或是code.exe所依赖的后面的code.o文件的文件修改时间要比code.exe这个文件新(可以用 touch测试 - 前面讲过touch可以修改文件最近一次被修改的时间),那么,他就会执行后面所定义的命令来生成code.exe这个文件。
  4. 如果code.exe所依赖的code.o文件不存在,那么make会在当前文件中找目标为code.o文件的依赖性,如果找到则再根据那一个规则生成code.o文件。(这有点像一个堆栈的过程
  5. 当然,你的C文件和H文件是存在的啦,于是make会生成 code.o文件,然后再用 code.o文件声明make的终极任务,也就是执行文件code.exe了。
  6. 这就是整个make的依赖性,make会一层又一层地去找文件的依赖关系,直到最终编译出第一个目标文件。
  7. 在找寻的过程中,如果出现错误,比如最后被依赖的文件找不到,那么make就会直接退出,并报错,而对于所定义的命令的错误,或是编译不成功,make根本不理。
  8. make只管文件的依赖性,即,如果在我找了依赖关系之后,冒号后面的文件还是不在,那么对不起,我就不工作啦。

makefile / make会自动根据文件中的依赖关系,进行自动推导,帮助我们执行所有的相关的依赖方法。

在这里插入图片描述


  • makefile文件中,保存了编译器和链接器的参数选项,并且描述了所有源文件之间的关系。make程序会读取makefile文件中的数据,然后根据规则调用编译器,汇编器,链接器产生最后的输出。
  • Makefile里主要包含了五个东西:显式规则、隐晦规则、变量定义、文件指示和注释。1. 显式规则说明了,如何生成一个或多个目标文件。2. make有自动推导的功能,所以 隐晦规则可以让我们比较粗糙地简略地书写makefile ,比如源文件与目标文件之间的时间关系判断之类。3. 在makefile中可以定义变量makefile被执行时,其中的变量都会被扩展到相应的引用位置上。4. 通常使用 $(var) 表示引用变量文件指示。包含在一个makefile中引用另一个makefile,类似C语言中的include。5. 注释makefile中可以 使用 # 在行首表示行注释
  • 默认的情况下,make命令会在当前目录下按顺序找寻文件名为“GNUmakefile”、“makefile”、“Makefile”的文件

3.3 项目清理

  • 工程是需要被清理的
  • clean这种,没有被第一个目标文件直接或间接关联,那么它后面所定义的命令将不会被自动执行,不过,我们可以显示要make执行。 即命令——“make clean”,以此来清除所有的目标文件,以便重编译。
  • 但是一般我们这种clean的目标文件,我们将它设置为伪目标,用.PHONY 修饰,伪目标的特性是,总是被执行的。 makefile中的伪对象表示对象名称并不代表真正的文件名,与实际存在的同名文件没有相互关系,因此伪对象不管同名目标文件是否存在都会执行对应的生成指令。伪对象的作用有两个,1. 使目标对象无论如何都要重新生成。2. 并不生成目标文件,而是为了执行一些指令.

在这里插入图片描述
于是我们便可使用vim编写如上内容。里面$相当于取值操作,@最终会被替换目标文件,而^会被替换为依赖方法。

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

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

相关文章

JuiceSSH结合Cpolar实现公网远程SSH访问内网Linux系统

文章目录 1. Linux安装cpolar2. 创建公网SSH连接地址3. JuiceSSH公网远程连接4. 固定连接SSH公网地址5. SSH固定地址连接测试 处于内网的虚拟机如何被外网访问呢?如何手机就能访问虚拟机呢? cpolarJuiceSSH 实现手机端远程连接Linux虚拟机(内网穿透,手机端连接Linux虚拟机) …

安全防御第七次实验

需求:在FW7和FW8之间建立一条IPSEC通道保证10.0.2.0/24网段可以正常访问到192.168.1.0/24 一、NAT配置 FW4: FW6: 二、在FW4上做服务器映射 三、配置IPSEC FW5: FW6: 四、防火墙上的安全策略 FW4: FW5:…

Chrome安装Axure插件

打开原型目录/resources/chrome,重命名axure-chrome-extension.crx,修改后缀为rar,axure-chrome-extension.rar 解压到axure-chrome-extension目录打开Chrome,更多工具->扩展程序,打开开发者模式,选择加…

电机控制系列模块解析(第八篇)—— 高频注入法

一、基本原理 在电机控制领域,高频方波注入法常用于估计转子的位置和转速。其工作原理是每隔一定的时间间隔在电机输出电压上叠加一个电压脉冲。然后,在两相静止坐标系下或者同步旋转坐标系下对采样时刻的电压和电流进行相应的计算,以实现对…

专业设计者必备!2024年精选作品集模板,一键替换高品质样机,展现出色!

现在是金三银四求职季。你已经开始制作或更新作品集了吗?作品集是展示设计师设计才能、创新思维和项目经验的重要媒介。随着设计师经验的积累和技能的进步,一个高质量的作品集将不断更新升级。在这里,即时设计为您提供了100多种作品集模板资源…

Transformer中的 Add Norm

Transformer中的 Add & Norm flyfish Add 同一个意思 Residual connections,Skip Connections Norm 包括Post layer normalization和Pre layer normalization Post layer normalization:Transformer 论文中使用的方式,将 Layer norm…

神经网络softmax算法与卷积层

多类分类: 多类是分类算法中的一种,它区别于我们的0,1这样子的二进制分类,它会有多个分类的标签,让我们去取其中的一个。 softmax函数: softmax回归算法是我们的sigmoid回归的推广。 上图就是softmax运…

一文搞懂如何自己写一个Python库

你是否曾想过为自己的Python项目编写一个库,以便在不同项目中重复使用代码? 并且能在PyPI仓库中发布,并通过pip install 库名来安装使用 编写Python库可能看起来有些复杂,但实际上并非如此。本文将为你提供一份简明的指南&#x…

【虚拟换衣+论文+代码】2403.OOTDiffusion:高分辨率(1024x768)可控的虚拟试穿(已开源,暂不能训练)

项目地址:https://github.com/levihsu/OOTDiffusion 试用地址:https://ootd.ibot.cn/ 论文地址:2403.OOTDiffusion: 基于衣服融合的可控虚拟试穿潜在扩散 | readpaper arxiv: Outfitting Fusion based Latent Diffusion for Controllable Vir…

如何防御udp攻击

UDP Flood是互联网上最经典的DDoS(Distributed Denial of Service)攻击之一。攻击者在短时间内向目标设备发送大量的UDP报文,导致链路拥塞甚至网络瘫痪。一般的UDP报文由攻击工具伪造,通常在数据段具备相同的特征,另一…

社区店选址标准:如何选择适合你业务的理想位置

选址是实体店成功的关键因素之一,而社区店更是要紧密结合社区的特点来选择。 作为一名鲜奶吧开店5年的创业者,我将为大家分享一些实用的社区店选址标准。 1、社区类型: 首先要明确你的目标客户群体,然后选择与之匹配的社区类型…

SpringCloudAlibaba微服务之Nacos架构及基础概念梳理

SpringCloudAlibaba微服务之Nacos架构及基础概念梳理 文章目录 SpringCloudAlibaba微服务之Nacos架构及基础概念梳理1. 官网介绍1. 简介2. Naocs是什么3. Nacos 地图4. Nacos 生态图 2. Nacos 架构1. 基本架构及概念1. 服务 (Service)2. 服务注册中心 (Service Registry)3. 服务…

基于模拟退火算法(SA)的TSP(Python实现)

本篇文章是博主在最化优学习、人工智能等领域学习时,用于个人学习、研究或者欣赏使用,并基于博主对相关等领域的一些理解而记录的学习摘录和笔记,若有不当和侵权之处,指出后将会立即改正,还望谅解。文章分类在最优化算…

Kubernetes-2

Kubernetes学习第二天 k8s-21、Kubernetes的核心组件2、pod2.1、什么是pod 3、3种启动pod的方式3.1、命令行启动pod3.1.1、执行下面命令,背后发生了什么? 3.2、启动一个pod背后发生了什么3.3、使用yml文件3.3.1、标准的pod3.3.2、使用部署控制器启动pod3…

web服务,C/S框架,单设备登陆实现方案

背景: 原登陆接口,校验密码通过后,使用springsession记录会话信息,将信息存入在redis中 基于原逻辑进行多设备登陆开发,默认的时候多设备登陆开关开启,即按原来逻辑处理,只要密码登陆校验成功之后,都会将当前的会话信息存入redis中. 当多设备开关关闭时候,同一个账号同一时间只…

Linux运维:实现光盘开机自动挂载、配置本地yum源教程

Linux运维:实现光盘开机自动挂载、配置本地yum源教程 一、光盘开机自动挂载1、检查光驱设备2、创建挂载点3、编辑/etc/fstab文件4、测试挂载 二、配置本地yum源(挂载光盘或ISO文件)1、挂载ISO文件2、创建YUM仓库配置文件3、清理YUM缓存并测试 💖The Begi…

《TCP/IP详解 卷一》第13章 TCP连接管理

目录 13.1 引言 13.2 TCP连接的建立与终止 13.2.1 TCP半关闭 13.2.2 同时打开与关闭 13.2.3 初始序列号 13.2.4 例子 13.2.5 连接建立超时 13.2.6 连接与转换器 13.3 TCP 选项 13.3.1 最大段大小选项 13.3.2 选择确认选项 13.3.3 窗口缩放选项 13.3.4 时间戳选项与…

专业140+总430+电子科技大学858信号与系统考研经验成电电子信息与通信工程,电科大,真题,大纲,参考书。

今年考研成绩出来,初试专业课858信号与系统140,总分430,其余各门分数都比较平稳,总分好于自己估分,应群里很多同学要求,我总结一下自己的复习经验。首先我是一个大冤种,专业课资料学长给了一套&…

【工作实践-07】uniapp关于单位rpx坑

问题:在浏览器页面退出登录按钮上“退出登录”字样消失,而在手机端页面正常;通过查看浏览器页面的HTML代码,发现有“退出登录”这几个字,只不过由于样式问题,这几个字被挤到看不见了。 样式代码中有一行为&#xff1a…

TQ15EG开发板教程:创建运行petalinux2019.1

工程网盘链接:https://pan.baidu.com/s/1vFRpzmbifXt7GypU9aKjeg 提取码:0ylh 首先需要使用与petalinux相同版本的vivado创建工程,与之前不同的是在创建硬件设计时需要勾选上添加bit文件,所以要在生成bit文件之后再创建硬件设计…