程序的编译和链接

简介: 程序必须载入内存中。在有操作系统的环境中:一般这个由操作系统完成。在独立的环境中,程序的载入必须由手工安排,也可能是通过可执行代码置入只读内存来完成。程序的执行便开始。接着便调用main函数。开始执行程序代码。这个时候程序将使用一个运行时堆栈(stack),存储函数的局部变量和返回地址。程序同时也可以使用静态(static)内存,存储于静态内存中的变量在程序的整个执行过程一直保留他们的值。终止程序。正常终止main函数;也有可能是意外终止。

@TOC

程序的编译和链接

程序的两种环境

在ANSI C的任何一种实现中,存在两个不同的环境。

第1种是翻译环境,在这个环境中源代码被转换为可执行的机器指令。

第2种是执行环境,它用于实际执行代码

翻译环境

平时我们写的程序都是一个个的源文件,那么这些文件是怎么生成.exe可执行文件的呢?这就是接下来我们要详细研究的内容

笼统的来讲,大致过程可以用下图来表示:

image-20230311141752312

组成一个程序的每个源文件通过编译过程分别转换成目标代码(object code)。

每个目标文件由链接器(linker)捆绑在一起,形成一个单一而完整的可执行程序。

链接器同时也会引入标准C函数库中任何被该程序所用到的函数,而且它可以搜索程序员个人的程序库,将其需要的函数也链接到程序中。

详解编译和链接

编译,其实严格来说应该叫做翻译,因为翻译其实还分多个步骤,分别为预处理,编译,汇编。在VS中每一步骤是观察不到的,所以我们使用GCC编译器来观察现象,研究清楚每个步骤都是做什么的。

预处理

image-20230311144819549

可以看到我这里有一个test.c文件,里面写了这样一段代码,这时候我们来看一下对它进行编译的第1步预处理,究竟做了些什么事情,我们用GCC来执行下面的指令:

gcc test.c -E > test.i

这句指令意思就是将编译test.c到预处理那步就停下来,并将所编译的信息重定向到test.i中,然后我们打开test.i看一下,

image-20230311144926051

实际上已经不存在什么定义的宏了,而是直接被替换,另外还值得注意的是原本只有十几行的代码,经过预处理之后变成了850行,可以看到预处理做的事情其实还是蛮多的,但是重点我们就是来观察一下现象,知道预处理这步到底做了些什么就可以了,所谓预处理就是对一些文本进行操作,

总结如下:

1.#include 头文件的包含,

2.#define 宏替换

3.删除注释

都是一些对文本的操作

编译

有了第一步的经验,我们可以来看一下编译的步骤,指令如下:

gcc test.i -S > test.s

image-20230311145252525

可以发现,我们的代码变成了汇编语言,这就是一个重要的步骤,其实翻译成汇编语言之外,还有语义分析,语法分析等等,你的一些语法错误等等就是这一步检查出来的,另外还有一个很重要的步骤是进行符号汇总,为什么说它重要呢,其实是为下一步生成符号表做准备。下一步再说,总结编译步骤:

编译:

1.语法分析

2.语义分析

3.符号汇总

4.翻译成汇编语言

等等

汇编

同样的操作:

gcc test.s -c > test.o

image-20230311150411754

好的,这下彻底看不懂了,实际上这是因为,编译之后的目标文件其实是二进制文件,是无法识别的,但是这种类型的文件有它自己的格式叫做elf,有个工具readelf是可以看这种类型的文件的具体内容的,这种文件内容实际上也是有特点,都是一段一段的,每一段放不同的信息。我们先说汇编这步做了一些什么事情,

汇编:

1.翻译成二进制

2.生成符号表

我们用readelf这个工具要看关注的也就是这个符号表,来了解一下:

image-20230311151254342

可以看到是有一堆选项,我们要用的就是-s,这个选项来看这个符号表

image-20230311151354133

这个就是我们汇编这步生成的符号表,这个符号表存储了文件中符号的信息,之前我们的示意图中已经说了,我们的源文件是有多个的,每个文件里面的函数变量当然也是多个的,那最后我们链接起来怎么找到这些符号呢?靠的就是这个符号表,它会记录下每个符号的信息,函数,变量,它们的地址等等,在后面的链接这步中按照这个符号表来寻找。

链接

我相信很多人可能早就听过,链接就是将本地多个源文件组合起来,并且引入一些外部的库等等,但是对它到底这个步骤是怎么实现的并不清楚,

今天就来研究清楚,先说链接这个步骤到底做了什么,

链接:

1.合并段表

2.符号表的合并和重定位

段表这个今天先暂时不讨论,到后期才能彻底理解,

段表概念:在分段式存储管理系统中,每个进程或程序都有一个或多个逻辑段,为使程序或称进程能正常运行,亦即,能从物理内存中找出每个逻辑段所对应的位置,在系统中为每个进程建立一张段映射表,简称段表,段表记录了进程中每一个段在内存中的起始地址(又称为 “基址” )、段号和段的长度。

重点还是上面的符号表,符号表合并和重定位是什么意思呢?

举个例子:

image-20230311154303607

像是这个例子就能简单的描述一下,符号表的问题,我们知道每个文件最后都会生成一个目标文件,所以每个源文件的目标文件中都有一张符号表,我们就需要信息合并,当test.c文件中安装符号表去找Add函数时,发现找不到(其实这时候Add的地址是个无效地址),所以就会报出了错误,LNK的错误一定是链接时发生的错误,无法解析的外部符号就是根据符号表中的信息去找Add这个符号找不到。

如果add.c中将函数名改成正确的Add,在链接时符号表合并,就会将add.c中Add函数的地址重定向到合并之后的符号表中,这样才能够顺序执行。

如果当我们把test.c中的声明去掉,代码也是可以很好的跑起来的,编译器仅仅是报个警告,为什么呢?我想应该就很容易理解了,即使你没有声明,但是在最后符号表合并的时候依旧是很好的进行了合并。所以最后的结果是没有一点问题的。

运行环境

程序执行的过程:

程序必须载入内存中。在有操作系统的环境中:一般这个由操作系统完成。在独立的环境中,程序的载入必须由手工安排,也可能是通过可执行代码置入只读内存来完成。

程序的执行便开始。接着便调用main函数。

开始执行程序代码。这个时候程序将使用一个运行时堆栈(stack),存储函数的局部变量和返回地址。程序同时也可以使用静态(static)内存,存储于静态内存中的变量在程序的整个执行过程一直保留他们的值。

终止程序。正常终止main函数;也有可能是意外终止。

相关文章
|
28天前
|
人工智能 监控 安全
提效40%?揭秘AI驱动的支付方式“一键接入”系统
本项目构建AI驱动的研发提效系统,通过Qwen Coder与MCP工具链协同,实现跨境支付渠道接入的自动化闭环。采用多智能体协作模式,结合结构化Prompt、任务拆解、流程管控与安全约束,显著提升研发效率与交付质量,探索大模型在复杂业务场景下的高采纳率编码实践。
296 26
提效40%?揭秘AI驱动的支付方式“一键接入”系统
|
28天前
|
人工智能 IDE 开发工具
从6人日到1人日:一次AI驱动的客户端需求开发实战
从6人日到1人日:一次AI驱动的客户端需求开发实战
从6人日到1人日:一次AI驱动的客户端需求开发实战
|
27天前
|
人工智能 缓存 数据可视化
复盘:利用 Coze+Kimi 搭建自动财报分析“金融助理”的方法
本文手把手教你如何利用Coze与Kimi搭建智能财报分析助手。从环境部署、工作流设计到专业提示词编写,完整展示5分钟内实现财务指标计算、趋势分析和风险提示的自动化流程,有效提升投研效率。
|
存储 弹性计算 安全
使用OSS上传下载文件
阿里云对象存储OSS(Object Storage Service)是一款海量、安全、低成本、高可靠的云存储服务,可以提供多种用途,最简单的使用方式是做文件存储,用来上传下载文件啊
4328 0
使用OSS上传下载文件
|
28天前
|
监控 算法 测试技术
大模型推理服务优化:动态批处理与连续批处理技术
本文系统阐述大语言模型推理服务中的关键技术——动态批处理与连续批处理。通过分析传统静态批处理的局限性,深入解析动态批处理的请求调度算法、内存管理策略,以及连续批处理的中断恢复机制。文章包含完整的服务架构设计、核心算法实现和性能基准测试,为构建高性能大模型推理服务提供全面解决方案。
188 3
|
28天前
|
机器学习/深度学习 测试技术
先SFT后RL但是效果不佳?你可能没用好“离线专家数据”!
通义实验室Trinity-RFT团队提出CHORD框架,通过动态融合SFT与RL,解决大模型训练中“越学越差”“顾此失彼”等问题。该框架引入细粒度Token级权重与软过渡机制,实现从模仿到超越的高效学习,在数学推理与通用任务上均显著提升性能,相关代码已开源。
193 0
|
SQL 人工智能 分布式计算
基于阿里云PAI平台搭建知识库检索增强的大模型对话系统
基于原始的阿里云计算平台产技文档,搭建一套基于大模型检索增强答疑机器人。本方案已在阿里云线上多个场景落地,将覆盖阿里云官方答疑群聊、研发答疑机器人、钉钉技术服务助手等。线上工单拦截率提升10+%,答疑采纳率70+%,显著提升答疑效率。
|
机器学习/深度学习 存储 人工智能
英伟达 H100 vs. 苹果M2,大模型训练,哪款性价比更高?
训练和微调大型语言模型对于硬件资源的要求非常高。目前,主流的大模型训练硬件通常采用英特尔的CPU和英伟达的GPU。然而,最近苹果的M2 Ultra芯片和AMD的显卡进展给我们带来了一些新的希望。
1993 0
|
机器学习/深度学习 传感器 自动驾驶
未来之路:大模型技术在自动驾驶的应用与影响
本文深入分析了大模型技术在自动驾驶领域的应用和影响,万字长文,慢慢观看~ 文中首先概述了大模型技术的发展历程,自动驾驶模型的迭代路径,以及大模型在自动驾驶行业中的作用。 接着,详细介绍了大模型的基本定义、基础功能和关键技术,特别是Transformer注意力机制和预训练-微调范式。 文章还介绍了大模型在任务适配性、模型变革和应用前景方面的潜力。 在自动驾驶技术的部分,详细回顾了从CNN到RNN、GAN,再到BEV和Transformer结合的技术迭代路径,以及占用网络模型的应用。 最后,文章重点讨论了大模型如何在自动驾驶的感知、预测和决策层面提供赋能,突出了其在该领域的重要性和影响力。
2245 56
|
10月前
|
机器学习/深度学习 PyTorch 调度
内部干货 | 基于华为昇腾910B算力卡的大模型部署和调优-课程讲义
近日上海,TsingtaoAI为某央企智算中心交付华为昇腾910B算力卡的大模型部署和调优课程。课程深入讲解如何在昇腾NPU上高效地训练、调优和部署PyTorch与Transformer模型,并结合实际应用场景,探索如何优化和迁移模型至昇腾NPU平台。课程涵盖从模型预训练、微调、推理与评估,到性能对比、算子适配、模型调优等一系列关键技术,帮助学员深入理解昇腾NPU的优势及其与主流深度学习框架(如PyTorch、Deepspeed、MindSpore)的结合应用。
3487 13