编译和链接以及makefile

编译和链接以及makefile

问题引出,为什么我们会忽略编译和链接这个步骤

在这里插入图片描述

  • 一定都会用到但却很少被重视的步骤——编译和链接,通常这两个步骤被我们的IDE封装的很完美,我们一般都是一件构建。

在这里插入图片描述

  • 但是一旦遇到错误的时候,尤其是链接相关的错误,很多人就束手无策了,所以今天就跟大家一起深入探讨一下编译和链接的整个过程。

编译

在这里插入图片描述

  • 首先,什么是编译呢,编译的过程其实就是将我们程序的源代码,翻译成CPU能够直接运行的机器代码。
#include <stdio.h>int add(int a, int b);int main()
{printf("Hello, World!\n");int result = add(5, 5);return 0;
}
  • 比如我们写了一个源文件main.c,里面简单输出了一行文字,并且调用了一个函数add,而这个函数add被定义在另一个源文件math.c中。
int add(int a,int b)
{return a+b;
}
  • 这里我们就可以调用gcc -c来分别编译这两个源文件,需要注意的是,编译永远都是以单个源文件为单位的,在实际开发中,我们通常会将不同功能的代码分散到不同的源文件,一方面方便代码的阅读和维护,同时也提升了软件构建的速度。、

在这里插入图片描述

  • 比如你修改了一个源文件,那么只需要单独编译它这一个,而不需要浪费时间重新编译整个工程,可以看到在编译之后会生成两个扩展名为.o的文件,它们被称作目标文件(Object File),目标文件是一个二进制的文件,文件格式是ELF(Executable and Linkable Format),linux下所有可执行文件的通用格式,相应的Windows使用的是另一种格式PE,它们虽然互不兼容但在结构上非常相似,都是对二进制代码的一种封装。

在这里插入图片描述

  • 我们可以在文件头部找到可执行文件的基本信息比如支持的操作系统,机器类型等等。

在这里插入图片描述

  • 后面是一系列的区块,被叫做sections,里面有我们的机器代码还有程序的数据等等,比如.text是代码区,里面是之前编译好的机器代码,.data是数据区,里面保存了我们初始化的全局变量、局部静态变量等等,后面还有一些其他的区块稍后再说。

在这里插入图片描述

  • 需要注意的是,目标文件虽然包含了编译之后的机器代码,但它并不能够直接执行,操作系统也不允许你去执行它。

在这里插入图片描述

  • 因为在编译的过程中,我们用到了尚未定义的函数add,而我们主程序中的add其实只是一句声明而已,它被定义在另一个模块math.c中,这同样也包括我们用到的标准库中的printf,如果我们去查看stdio.h头文件,其中的printf只是一句函数的声明而已,换句话说,我们在编译main.c的时候,编译器是完全不知道printf和add函数的存在的,比如它们位于内存的哪个区块,代码长什么样,都是不知道的,因此编译器只能将这两个函数的跳转地址暂时先设为0,随后在连接的时候再去修正它。

在这里插入图片描述

  • 比如我们来看一下main.o这个目标文件中的内容,这里的mian是编译之后的主函数代码,左边是机器代码右边是对应的反汇编,可以看到这里的两个call指令,很明显它们分别对应之前调用的printf和add函数,但是你会发现它们的跳转地址都被设成了0,而这里的0会在后面链接的时候被修正。

链接

在这里插入图片描述

  • 另外为了让链接器能够定位到这些需要被修正的地址,在代码块中我们还可以找到一个重定位表,比如在.text区块中,需要被重定位的两个函数printf和add,它们位于偏移量14和23的位置,后面是地址的类型和长度,这和我们之前看到的机器代码是一一对应的。

在这里插入图片描述

  • 我们将另一个源文件math.c也编译出来,最后连同main.o一起链接生成一个独立的可执行文件。我们用到的还是gcc命令,后面传入之前编译的这两个目标文件,随后在目录下可以找到生成的可执行文件main,而这个main就可以直接运行了。

在这里插入图片描述

  • 所以链接其实就是将编译之后的所有目标文件,连同用到的一些静态库、运行时库,组合拼装成一个独立的可执行文件,其中就包括我们之前提到的地址修正,在这个时候,链接器就会根据我们的目标文件或者静态库中的重定位表,找到那些需要被重定位的函数、全局变量,从而修正它们的地址。

在这里插入图片描述

  • 但如果我们在链接的时候,忘记提供必须的目标文件,比如这里的math.o,由于链接器找不到add函数的实现,于是报错“引用未定义”,或者有的编译器也叫它“符号未定义(undefined symbols)”,意思就是我们用到了add但链接器却无法找到它的定义,因此只能报错。

makefile

在这里插入图片描述

  • 如果我们每次都手动编译再链接显然不够高效,实际开发也没有人这么做,通常我们都是用各种各样的IDE或者构建工具帮我们自动化了。

在这里插入图片描述

  • 所以这里引出一种最简单的构建工具makefile(make),可能很多人对它的印象是很古老。但其实makefile除了软件构建之外还有许多其他的奇技淫巧,比如用它来自动生成文档等等,像很多现在的项目也都还在用它,譬如Android OS的构建等等,makefile的核心其实是对“依赖(Dependency)”的管理,比如要构建main则需要main.o和math.o这两个文件,同时执行下面这条链接指令,如果要构建main.o又需要main.c这个文件,同时执行下面这条“编译”指令。

在这里插入图片描述

  • 然后你会发现,makefile其实就是在定义一颗依赖树,你要构建最上方的这个目标就需要提供下面这些节点的文件,然后这样层层地递归下去。

在这里插入图片描述

  • 有了makefile以后我们可以调用make命令,后面跟上目标的名称main,它会自动根据我们的“依赖树”递归地去构建这个可执行文件,当然第一次运行由于所有叶子节点都不存在,make会自动构建所有的依赖,包括其中的目标文件,但如果我们再运行一次make由于所有的文件都已经存在并且是最新的,make就不会在重复构建了。

在这里插入图片描述

在这里插入图片描述

  • 此时如果我们再单独修改一下main.c文件,由于main.c只会影响main.o从而影响最后的可执行文件main,所以make只会去重新生成这两个相关的文件,从而避免了其他不必要的文件编译,其实所有的现代化构建工具,都用到了相同的原理——对依赖的管理,只不过加入了一些更实用的功能比如脚本语言的支持,第三方库的管理等等。

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

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

相关文章

动手学深度学习(pytorch土堆)-05-1神经网络

Neural network 以下是 torch.nn 库中各个组件的详细分类&#xff1a; 1. 容器 (Containers) torch.nn.Sequential: 顺序容器&#xff0c;用于将层按顺序堆叠在一起。torch.nn.ModuleList: 模块列表&#xff0c;用于存储多个子模块。torch.nn.ModuleDict: 模块字典&#xff…

Pycharm出现Please specify a different SDK name报错,但是看不到重名环境解决方案

这句话的意思是出现了重名的环境 &#xff0c;一般情况下删除重名的环境即可解决问题。做法如下图所示 1&#xff0c;点击右上角齿轮→settings&#xff08;或者File→settings&#xff09;进入Python Interpreter 2.点击这个沙漏按键&#xff0c;你会发现多了几个环境&#x…

minio的最大优势--运维(五)

前言&#xff1a; 前面讲了minio的简介、场景、单机部署、集群部署等内容&#xff0c;现在简单来讲讲它的运维工具。 一、Minio客户端使用&#xff08;这个中文文档没问题&#xff09; 官方文档地址&#xff1a;https://docs.min.io/docs/minio-client-quickstart-guide.html…

穿什么有这么重要?——装饰模式

文章目录 穿什么有这么重要&#xff1f;——装饰模式穿什么有这么重要&#xff1f;小菜扮靓第一版小菜扮靓第二版装饰模式小菜扮靓第三版商场收银程序再升级简单工厂策略装饰模式实现装饰模式总结 穿什么有这么重要&#xff1f;——装饰模式 穿什么有这么重要&#xff1f; 时…

手写redis实现分布式锁详细教程,满足可续锁、可重入等分布式锁条件

前言 本文将讨论的做一个高并发场景下避不开的话题&#xff0c;即redis分布式锁。比如在淘宝 的秒杀场景、热点新闻和热搜排行榜等。可见分布式锁是一个程序员面向高级的一门必修课&#xff0c;下面请跟着本篇文章好好学习。 redis分布式锁有哪些面试题 1.Redis做分布式的时…

执着追求与匠心独运 朵拉朵尚2024欧洲溯源 深入德国巴斯夫

执着追求与匠心独运 朵拉朵尚2024欧洲溯源 深入德国巴斯夫 前不久&#xff0c;朵拉朵尚踏上了其2024年欧洲溯源之旅的第三站—德国巴斯夫&#xff0c;一场旨在深化护肤智慧、共谋新品未来的深度交流盛宴在此拉开帷幕。作为全球最大的化工公司&#xff0c;巴斯夫不仅以其卓越的…

电脑录屏工具哪个好用?推荐新手几款实用工具介绍

现在不管是录个教学视频教教别人&#xff0c;还是直播游戏给粉丝看&#xff0c;或者是展示你的产品&#xff0c;都得用到它。但是市面上的录屏软件多得让人眼花缭乱&#xff0c;新手可能一看就懵了。别急&#xff0c;今天我就给你介绍几个特别好用的电脑录屏工具&#xff0c;不…

攻克大模型面试!RAG基础与应用痛点一网打尽!

RAG相关理论知识与经验整理。 谈到大模型在各垂直领域中的应用&#xff0c;一定离不开RAG&#xff0c;本系列开始分享一些RAG相关使用经验&#xff0c;可以帮助大家在效果不理想的时候找到方向排查或者优化。 本系列以医疗领域为例&#xff0c;用面试题的形式讲解RAG相关知识…

唤醒金融数据中台:我的数据驱动秘籍

目录 一、明析业务痛点和机会点二、数据驱动精准化营销三、一体化数据平台——整合金融数据1. 数据整合与标准化2. 数据服务与共享3.业务体系集中化 四、强化金融数据安全&#xff0c;筑牢数据保护防线 在当今数字化时代的大潮中&#xff0c;数据无疑是金融行业最耀眼的财富。作…

销售管理中的难题,你是否也深陷其中?

销售管理中的难题似乎总是让人头疼。从客户跟进不及时&#xff0c;到销售数据分析不足&#xff0c;再到团队沟通不畅&#xff0c;导致商机频频流失。销售目标总是难以达成&#xff0c;业绩压力越来越大&#xff0c;但解决方案却总是力不从心。面对这样的问题&#xff0c;你是不…

Chainlit集成LlamaIndex并使用通义千问模型实现AI知识库检索网页对话应用增强版

前言 之前使用Chainlit集成LlamaIndex并使用通义千问大语言模型的API接口&#xff0c;实现一个基于文档文档的网页对话应用。 可以点击我的上一篇文章《Chainlit集成LlamaIndex并使用通义千问模型实现AI知识库检索网页对话应用》 查看。 本次针对上一次的代码功能进一步的完善…

推动公平学习与身份归一化的视网膜神经疾病数据集

人工智能咨询培训老师叶梓 转载标明出处 在机器学习领域&#xff0c;公平性&#xff08;也称为公正性或平等性&#xff09;是一个日益受到关注的话题&#xff0c;它对于社会的福祉至关重要。然而&#xff0c;目前缺乏专门用于公平学习且包含成像数据的公共医学数据集&#xff…

分苹果 - 华为OD统一考试(E卷)

2024华为OD机试(E卷+D卷+C卷)最新题库【超值优惠】Java/Python/C++合集 题目描述 A 和 B 两个人要分苹果。A 希望按照他的计算规则得到平均分配的苹果,而 B 希望在满足 A 的条件下获得尽可能多的苹果量。 A 的计算规则是按照二进制加法进行,并不计算进位。例如,12 + 5 =…

CAT1 DTU软硬件设计开源资料分析(TCP协议版本 )

一、CAT1 DTU方案简介&#xff1a; 远程终端单元DTU&#xff0c;一种针对通信距离较长和工业现场环境恶劣而设计的具有模块化结构的、特殊的计算机测控单元&#xff0c;它将末端检测仪表和执行机构与远程控制中心相连接。 奇迹TCP DTU版本DTU&#xff0c;用于将远程现场的传感…

VoIP协议

VoIP协议是VoIP业务的规范标准。我们都知道VoIP业务有着压倒性的优势。随着网络应用的多元化和低成本化发展&#xff0c;VoIP业务直接冲击着传统通信市场&#xff0c;那么目前VoIP协议目前常用的协议,如H.323、SIP、MEGACO和MGCP。 H.248 H.248是定义网关控制协议的ITU建议书…

分布式光伏发电站数据采集设备管理硬件解决方案

随着全球能源结构的转型和可再生能源的快速发展&#xff0c;光伏发电作为重要的清洁能源之一&#xff0c;在能源市场中占据了越来越重要的位置。AcrelCoud-1200分布式光伏运维云平台通过监测光伏站点的逆变器设备&#xff0c;气象设备以及摄像头设备&#xff0c;帮助用户管理分…

【Linux系统编程】第二十弹---进程优先级 命令行参数 环境变量

✨个人主页&#xff1a; 熬夜学编程的小林 &#x1f497;系列专栏&#xff1a; 【C语言详解】 【数据结构详解】【C详解】【Linux系统编程】 目录 1、进程优先级 2.1、什么是优先级 2.2、优先级的描述 2.3、优先级与权限的关系 2.4、为什么要有优先级 2.5、Linux优先级的…

某oa命令执行漏洞挖掘思路

《网安面试指南》http://mp.weixin.qq.com/s?__bizMzkwNjY1Mzc0Nw&mid2247484339&idx1&sn356300f169de74e7a778b04bfbbbd0ab&chksmc0e47aeff793f3f9a5f7abcfa57695e8944e52bca2de2c7a3eb1aecb3c1e6b9cb6abe509d51f&scene21#wechat_redirect 《Java代码审…

图像修复(Inpainting)技术的前沿模型与数据集资源汇总

图像修复&#xff08;Image Inpainting&#xff09;是一种计算机视觉技术&#xff0c;旨在填补图像中的缺失区域或去除图像中的不需要部分&#xff0c;使其看起来自然且无明显痕迹。其目标是根据图像的上下文信息和周围像素来推断和重建缺失区域的内容&#xff0c;以生成逼真且…

《机器学习》周志华-CH7(贝叶斯分类)

7.1贝叶斯决策论 对分类任务而言&#xff0c;在所有相关概率已知的理想情形下&#xff0c;贝叶斯决策论考虑如何基于这些概率核误判损失来选择最优的类别标记。 R ( x i ∣ x ) ∑ j 1 N λ i j P ( c j ∣ x ) \begin{equation} R(x_{i}|x)\sum_{j1}^{N}\lambda_{ij}P(c_{j}…