【iOS内存管理-编译链接的过程】

这篇具有很好参考价值的文章主要介绍了【iOS内存管理-编译链接的过程】。希望对大家有所帮助。如果存在错误或未考虑完全的地方,请大家不吝赐教,您也可以点击"举报违法"按钮提交疑问。

前言

就我而言,iOS开发的过程中接触到的编译链接方面的知识很少,这部分知识还是很重要的。

对于iOS的编译链接过程来说并不难,和微机原理的汇编过程还是挺像的。今天对于编译链接的过程学习和了解一下。
参考:iOS程序员的自我修养-编译、链接过程
参考:iOS编译过程

计算机语言

计算机语言有机器语言,汇编语言和高级语言。对于OC这种高级语言来说分为 编译语言和解释型语言。
【iOS内存管理-编译链接的过程】,ios,cocoa,macos,开发语言,swift

  • 编译型语言(一次性翻译)
    • 特点:一次性翻译。
    • 编译型语言的程序只要等编译器编译之后,每次运行都可以直接运行,OC和swift就是如此。
    • 优点就是执行速度够快,因为不用多次编译。
    • 缺点就是可移植性差,编译的时候需要对操作系统的库做出链接,可能需要不同的库。
  • 解释型语言(逐步翻译)
    • 解释语言编写的程序在每次运行时都需要通过解释器对程序进行动态解释和执行,如php,javascript
      即解释一条代码,执行一条
    • 优点就是可移植性好,不需要繁杂的系统库。
    • 缺点显而易见就是执行速度慢,不是一次性的。

文件后缀名

在iOS的编译和链接过程中,不同的文件后缀名代表不同的文件类型和中间过程。

  • .i 文件:.i 文件是预处理器处理源代码之后生成的文件,其中包含了宏展开、条件编译等预处理操作后的代码。

  • .s 文件:.s 文件是汇编器生成的汇编代码文件。它将预处理器生成的 .i 文件翻译成机器指令的文本表示形式,每个汇编指令对应一条机器指令。

  • .o 文件:.o 文件是编译器生成的目标文件,也被称为对象文件。它包含了汇编器生成的机器指令以及一些符号表、重定位信息和其他调试信息。

  • .m 文件:.m 文件是 Objective-C 源代码文件的常见扩展名。它包含了 Objective-C 的代码,可以与 C 和 C++ 代码混合使用。

这些文件在编译和链接过程中的不同阶段产生,并在整个过程中相互转换和传递,最终生成可执行文件或库文件。

编译和链接的过程

上面说过OC/swift都是编译语言,在执行的时候通过编译器生成机器码,机器码可以直接在CPU上执行,效率更快。

OC的编译是基于Clang/ LLVM来编译的,简单了解LLVM是一个模块化的可重用的编译器和工具技术的集合,Clang是LLVM的子程序,C,C++,OC都是Clang的子程序。其目的就是更快的效率编译出更好的程序。

编译链接过程:预处理 -> 词法分析 -> 语法分析 -> 静态分析 -> 生成中间代码和优化 -> 汇编 -> 链接 =
预处理 -> 编译 -> 汇编 -> 链接
【iOS内存管理-编译链接的过程】,ios,cocoa,macos,开发语言,swift

编译链接

1,预处理:macro 宏, import 头文件替换及处理其他的预编译指令产生.i文件。(都是以#号开头)

2,编译:把预处理完的一系列文件进行一系列词法、语法、语义分析,并且优化后生成相应的汇编代码,产生.s文件

3,汇编:汇编器将汇编代码生成机器指令,输出目标文件,产生.o文件(根据汇编指令和机器指令的对照表一一翻译就可以了);

4,链接:在一个文件中可能会到其他文件,因此,还需要将编译生成的目标文件和系统提供的文件组合到一起,这个过程就是链接。经过链接,最后生成可执行文件

经过编译和链接,才会把写的代码转换成计算机能识别的二进制指令。

预处理(预编译)-> 产生.i文件

clang -E main.m -o main.i

处理源代码文件中的以"#"开头的预编译指令

  • "#define"删除并展开对应宏定义。
  • 处理所有的条件预编译指令。如#if/#ifdef/#else/#endif。
  • "#include/#import"包含的文件递归插入到此处。
  • 删除所有的注释"//或/**/"。
  • 添加行号和文件名标识。如“# 1 "main.m"”,编译调试会用到。

总结编译器在预处理阶段处理结果:

  • 宏替换 (在源码中使用的宏定义会被替换为对应的内容)
  • 头文件引入(#include,#import)使用对应文件.h的内容替换这一行的内容,所以尽量减少头文件中的#import,使用@class替代,把#import放到.m文件中。)
  • 处理条件编译指令(#if,#else,#endif)

编译 -> 产生.s文件

clang -S main.i -o main.s

编译过程也分为 词法分析 -> 语法分析 -> 静态分析 最后优化生成相应的汇编代码,得到.s文件

  • 词法分析 :这一步把源文件中的代码转化为特殊的标记流,源码被分割成一个一个的字符和单词,在行尾Loc中都标记出了源码所在的对应源文件和具体行数,方便在报错时定位问题。
    【iOS内存管理-编译链接的过程】,ios,cocoa,macos,开发语言,swift
  • 语法分析:这一步是把词法分析生成的标记流,解析成一个抽象语法树(abstract syntax tree – AST),同样地,在这里面每一节点也都标记了其在源码中的位置。此时运算符号的优先级确定了;有些符号具有多重含义也确定了,比如“*”是乘号还是对指针取内容;表达式不合法、括号不匹配等,都会报错。
    【iOS内存管理-编译链接的过程】,ios,cocoa,macos,开发语言,swift
  • 静态分析 :分析类型声明和匹配问题,如出现方法被调用但是未定义、定义但是未使用的变量等,以此提高代码质量。
    • 类型分析:在此阶段clang会做检查,最常见的是检查程序是否发送正确的消息给正确的对象,是否在正确的值上调用了正常函数。如果你给一个单纯的 NSObject* 对象发送了一个 hello 消息,那么 clang 就会报错,同样,给属性设置一个与其自身类型不相符的对象,编译器会给出一个可能使用不正确的警告。
    • 其他分析:关于是否多次初始化的检查。
  • 中间代码生成和优化: LLVM 会对代码进行编译优化,例如针对全局变量优化、循环优化、尾递归优化等,最后输出汇编代码。
  • 目标代码生成和优化: 根据中间语言生成依赖具体机器的汇编语言。并优化汇编语言。

汇编 -> 产生.o文件

clang -c main.s -o main.o

在这一阶段,汇编器将上一步生成的可读的汇编代码转化为机器代码。最终产物就是 以 .o 结尾的目标文件。使用Xcode构建的程序会在DerivedData目录中找到这个文件。

链接

clang main.o -o main

这一阶段是将上个阶段生成的目标文件和引用的静态库链接起来,最终生成可执行文件,链接器解决了目标文件和库之间的链接。

使用clang main.m生成可执行文件a.out(不指定名字默认为a.out),使用file a.out可以看到其类型信息:

a.out: Mach-O 64-bit executable x86_64

可以看出可执行文件类型为 Mach-O 类型,在 MAC OS 和 iOS 平台的可执行文件都是这种类型。

Mach-O(Apple官方文档)

【iOS内存管理-编译链接的过程】,ios,cocoa,macos,开发语言,swift

动态库和静态库

参考: iOS 静态库动态库看这里
链接的过程是将文件和引用的静态库和动态库链接起来,那么什么是动态库和静态库,他们又通过什么来链接的?

1. 静态库

静态库是静态链接库;是多个目标文件经过压缩打包后形成的文件包。以下都是静态库的类型

  • Windows 的 .lib
  • Linux 的 .a
  • MacOS 独有的 .framework

静态库

  • 优点::静态库在编译链接时会被整合到可执行文件中,使得程序在运行时独立运行,不需要依赖外部库。
    快速,由于整合到可执行文件中,静态库的调用通常比动态库的调用更快,因为不需要动态链接
  • 缺点: 生成的可执行程序较大。如果多个使用静态链接生成的程序同时运行会占用大量的内存空间静态库一旦被编译链接到可执行文件中,想要更新或替换静态库的代码需要重新编译整个程序。
    如果多个程序都使用相同的静态库,每个程序都会包含一份相同的库代码,造成重复代码

2. 动态库

  • 动态库是动态链接库,是实现共享函数库的一种方式。
  • 动态库在编译的时候不会被拷贝到目标程序中,目标程序只会存储下动态库的引用。
  • 真正用到动态库内的函数时才会去查找 - 绑定 - 使用函数。
  • 动态库的格式有:.framework.dylib.tbd……

动态库:

  • 优点:节省磁盘空间,且多个用到相同动态库的程序同时运行时,库文件会通过进程地址空间进行共享,内存当中不会存在重复代码,动态库的更新和替换比较方便,只需要替换动态库文件即可,不需要重新编译整个程序。动态库在程序运行时动态链接,使得程序文件较小,更易于分发和部署。
  • 缺点: 必须依赖动态库,否则无法运行。动态库在程序启动时需要加载,可能会稍微增加程序的启动时间。兼容性:由于不同操作系统或者不同版本的动态库可能存在兼容性问题,需要特别注意版本兼容性。

3. 动态库和静态库的区别

  • 静态库
    • 在编译时加载
    • 优点:代码装载和执行速度比动态库快。
    • 缺点:浪费内存和磁盘空间,模块更新困难。
  • 动态库
    • 在运行时加载
    • 优点:体积比静态库小很多,更加节省内存。
    • 缺点:代码装载和执行速度比静态库慢。
  • 备注:
    • 体积小于最小单位16k的静态库编译出来的动态库体积会等于16k。
    • 换成动态库会导致⼀些速度变低,但是会通过延迟绑定(Lazy Binding)技术优化。
    • 延迟绑定:首次使用的时候查找并记录方法的内存地址,后续调用就可以省略查找流程。

4. 动态库、静态库、framework是什么关系?

  1. 库是已经编译完成的二进制文件。
  2. 代码需要提供给外部使用又不想代码被更改,就可以把代码封装成库,只暴露头文件以供调用。
  3. 希望提高编译速度,可以把部分代码封装成库,编译时只需要链接。
  4. 库都是需要链接的,链接库的方式有静态和动态,所以就产生了静态库和动态库。

framework是一种文件的打包方式,把头文件,二进制文件,资源文件封装在一起,方便管理和分发。所以动态库和静态库的格式都有.framework;
【iOS内存管理-编译链接的过程】,ios,cocoa,macos,开发语言,swift

总结

编译链接是一iOS文件从开始到变成可执行的文件的过程,我们不去研究原理,但是对于整个流程的掌握还是很有必要的。文章来源地址https://www.toymoban.com/news/detail-573485.html

到了这里,关于【iOS内存管理-编译链接的过程】的文章就介绍完了。如果您还想了解更多内容,请在右上角搜索TOY模板网以前的文章或继续浏览下面的相关文章,希望大家以后多多支持TOY模板网!

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处: 如若内容造成侵权/违法违规/事实不符,请点击违法举报进行投诉反馈,一经查实,立即删除!

领支付宝红包 赞助服务器费用

相关文章

  • macOS Sonoma编译OpenCV源码输出IOS平台库

    1.macOS下载并编译OpenCV源码:  克隆源码: 主仓: git clone https://github.com/opencv/opencv.git 扩展仓:  git clone https://github.com/opencv/opencv_contrib.git    编译xcode源码需要CMake与XCode命令行工具 确认已安装CMake  确认已安装XCode  安装xcode command line tools 确认系统已安装python环境

    2024年02月10日
    浏览(61)
  • iOS--编译连接的过程_2

    一般可以将编程语言分为两种,编译语言和直译式语言。 像C++,Objective C都是编译语言。编译语言在执行的时候,必须先通过编译器生成机器码,机器码可以直接在CPU上执行,所以执行效率较高。 像JavaScript,Python都是直译式语言。直译式语言不需要经过编译的过程,而是在执行

    2024年02月16日
    浏览(35)
  • graphhopper-ios 编译过程详解

    GraphHopper 是一个快速且高效的 路径规划引擎 ,它默认使用 OpenStreetMap 和 GTFS 数据, 也可以导入其他数据源。它可以用作java库或独立的web服务器,去计算两个或多个点之间的线路的距离,时间,转弯指令和许多道路属性。除了“A-to-B”的路径规划能力之外,它还支持“snap to

    2023年04月18日
    浏览(28)
  • 如何建设一个用于编译 iOS App 的 macOS 云服务器集群?

    作者:京东零售 叶萌 现代软件开发一般会借助 CI/CD 来提升代码质量、加快发版速度、自动化重复的事情,iOS App 只能在 mac 机器上编译,CI/CD 工具因此需要有一个 macOS 云服务器集群来执行 iOS App 的编译。 今天就来谈谈如何建设 macOS 云服务器集群 最简单的方式就是购买一批

    2023年04月25日
    浏览(44)
  • iOS 内存管理和优化

    对内存管理和拓展有独特的描述 iOS学习-内存管理 比较详细说明内存的关系 iOS 内存管理机制与原理 iOS 内存泄漏排查方法及原因分析 对weak的实现原理描写详细 【iOS】—— weak的基本原理 iOS copy mutableCopy iOS 深拷贝与浅拷贝 对iOS的浅复制和深复制的深入解释 【iOS】深拷贝与浅

    2024年02月07日
    浏览(54)
  • 【iOS】ARC内存管理

    怎么说呢。经典再放送咯。 对象操作 对应的Objective-C方法 生成并持有对象 alloc/new/copy/mutableCopy等方法 持有对象 retain方法 释放对象 release方法 废弃对象 dealloc方法 iOS内存管理方案有三种,我们详细看下每种方案的实现及存在的意义。 标签指针 没有这种管理机制会引起内存浪

    2024年02月16日
    浏览(40)
  • iOS - 内存管理

    iOS 中,使用引用计数来管理 OC 对象的内存,新创建的 OC 对象引用计数默认是1,当引用计数减为0,OC对象就会销毁,释放其占用的内存空间。调用 retain 会让 OC 对象的引用计数 +1,调用 release 会让 OC 对象的引用计数-1。 当调用 alloc 、 new 、 copy 、 mutableCopy 方法返回了一个对

    2023年04月26日
    浏览(30)
  • 【iOS内存管理-内存的几大区域】

    iOS内存管理的第一篇章,了解iOS内存的五大分区。 iOS中,内存主要分为五大区域:栈区,堆区,全局区/静态区,常量区和代码区。总览图如下。 如上图所示,代码区是在低地址段存放,而栈区则存放在高地址段,并且各个分区之间不是连续的。 栈是 从高地址向低地址存储

    2024年02月16日
    浏览(34)
  • MacOS 14 系统 XCode15、 Flutter 开发 IOS

    MacOS14 Sonoma 安装 Flutter 开发环境 MacOS 系统 Flutter开发Android 环境配置 MacOS 系统 Flutter开发IOS 环境配置​​​​​​​ 前面我们已经在MacOS14 M3芯片上安装好 Flutter环境,包括开发工具 VsCode 、Android Stuiod,那么flutter如何开发IOS呢? 我们知道IOS开发语言为 objcet-c或者 swift,Flutter是

    2024年02月03日
    浏览(89)
  • 简单记录一次物理机配置zerotier planet根服务器并且配置安卓,ios,macos,华硕路由器互联的过程

            首先说明,本教程涵盖系统又。esxi6.7,centos7,安卓系统,苹果系统14.4.2越狱版,梅林系统。        一,搭建系统所用的设备有:dell740xd(做虚拟化)搭建根服务器,esxi安装教程就不说了,直接下载dell定制版,神秘代码激活。然后部署centos7虚拟机,这里需要注意

    2024年02月04日
    浏览(74)

觉得文章有用就打赏一下文章作者

支付宝扫一扫打赏

博客赞助

微信扫一扫打赏

请作者喝杯咖啡吧~博客赞助

支付宝扫一扫领取红包,优惠每天领

二维码1

领取红包

二维码2

领红包