iOS 静态库与动态库的一些面试题

静态库与动态库的一些面试问题

关于动/静态库一些问题的随笔,写的比较乱,啊哈哈哈哈哈😄

常用的文件格式

.a .dylib .framework .xcframework

1. 动态库和静态库的区别是什么?

nm -pa path

动态库所有符号信息都放到一起,
静态库按照.o文件进行分开存储

动态库的代码都是统一放在 Mach-O text section 段的
静态库的代码也是根据.o文件分开存储的

所以说静态库是一个.o文件的合集,静态库在往后链接就是可执行文件,也可以说是(动态库)。

静态库:.o -> .o合集 -> .a(静态库) 链接 -> 可执行文件(动态库)

在终端执行man ldld是链接器。)命令可以看到下面这段话:

image
  • 静态库: 是.o文件的合集,在每个.o里面都包含了全局符号,ld在需要解析一些符合的时候,才会从将这些符号从.o中链接到主App中。

  • 动态库:是一个最终链接完成的镜像,也就是编译链接的最终产物。所以动态库不可以做合并,所以在arm64和armv7同时支持的动态库也不是合并的,只是放在一起,Mach-O根据不同的环境针对性的链接。

所以就编译后的体积来说,同样的代码编译成动态库要小于静态库的体积。但是有时候从文件上来看并不是这样,这是因为静态库里面的.o文件并没有达到对齐所在的空间,所以存在比动态库小的可能。一般就是小于16k的时候,代码不多 。

查看命令 objdump --macho -x 文件路径 查看他的Mach-O段。

总结一下答案:

静态库也就是静态链接库,可以简单的看成目标文件的集合。即很多目标文件经过压缩打包后形成的文件。Windows下的.lib,Linux和Mac下的.a。Mac独有的.framework。

缺点: 浪费内存和磁盘空间,模块更新困难。

动态库:与静态库相反,动态库在编译时并不会被拷贝到目标程序中,目标程序中只会存储指向动态库的引用。等到程序运行时,动态库才会被真正加载进来。格式有.framework .dylib .tbd。现在苹果允许上架的动态库类型是.framework,有签名,阻止了热更新。

缺点:会导致一些性能损失。但是可以优化,比如延迟绑定(lazy Binding)技术。

如果您对Mach-O感兴趣,可以看看我的这篇文章Mach-O探索

2.静态库链接到主程序,静态库存放在什么位置?动态库呢?

静态库会在编译连接后与APP主程序合并成一个文件,也就是在我们的APP可执行文件中,动态库由于不能再合并了则需要单独签名放在frameworks文件夹中,在APP主程序文件中,保存着动态库的引用路径,等到APP运行的时候在进行加载。

image

3. 静态库、动态库与framework的关系?

静态库就是一些.o文件的合集,也就是静态链接库,一般是.a文件或者.framework文件,一般在APP包中看不到静态库,都会被合并的主程序可执行文件中。

动态库一般是.framework .dylib .tbd文件形式。动态库在编译时并不会被拷贝到目标程序中,目标程序中只会存储指向动态库的引用。等到程序运行时,动态库才会被真正加载进来

framework 是Mac OS/iOS 平台上的一种打包方式,将库的二进制文件,头文件和有关的资源文件打包到一起,方便管理和分发。

Framework和系统的 UIKit.Framework还是有很大区别的。系统的Framework不需要拷贝到目标程序中,我们自己做出来的Framework哪怕是动态的,最后也还是要拷贝到APP中(APP和Extension的Bundle是共享的),因此苹果又把Framework称为Embedded Framework。

Embedded Framework 也就是嵌入式Framework,开发中使用的动态库放入到ipa下的frameworks目录下,基于沙盒运行。不同的APP使用相同的动态库,并不会只在系统中存在一份。而是会在多个APP包中各自打包、签名、加载一份。

image

4. 什么是xcframework,使用有什么优势?

Xcode 会自动根据架构来将对应的架构拷贝到ipa中。Xcode 11以上支持。

XCFramework:是苹果官方推荐的、支持的,可以更方便的表示一个多个平台和架构的分发二进制库的格式。

需要Xcode11以上支持。
是为更好的支持Mac Catalyst和ARM芯片的macOS。
专门在2019年提出的framework的另一种先进格式。

目前支持:
iOS/iPad:arm64
iOS/iPad Simulator:x86_64 arm64
Mac Catalyst:x86_64 arm64
Mac:x86_64 arm64

和传统的framework相比:

  1. 可以用单个.xcframework文件提供多个平台的分发二进制文件;
  2. 与Fat Header相比,可以按照平台划分,可以包含相同架构的不同平台的文件;
  3. 在使用时,不需要再通过脚本去剥离不需要的架构体系。

关于Fat Header就是胖二进制文件(Mach-O)的头,也就是Mach-O Universal Files,通过header来记录不同架构在文件中的偏移量,segment占多个分页。所以对于多个架构这个header就会变得很大,也就是为什么要被叫做Fat Header

5. 什么是dead strip与-Objc参数与-force_load之间有联系吗?

dead strip与-Objc和-force_load之间没有什么联系。以下四个是对于加载静态库的四个级别

  • -noall_load:默认级别,也就是我们的APP默认不加载(链接)静态库中的内容,什么都没用到就不加载
  • -all_load:把所有代码全部加载进来,此时就可以看到静态库中的所有符号
  • -ObjC:只加载与OC相关的代码
  • -force_load <file>:指定的静态库才会被加载进来,可以通过这个来控制静态库的符号冲突,哪个作为主链接,哪个由ld扫描,不需要加载的就不加载了。当然解决符号冲突还可以通过加前缀的方式。

以上四个只针对我们的链接器去链接我们的静态库的时候使用。

那么dead strip是干什么的呢?我们通过man ld命令在终端里找到如下:

image

所有的.o文件,包括动态库都会生效。删除没有被入口函数(默认是main)访问的函数,或者导出这些符号。导出符号也就是其他文件的导入(#import)。我自己没用,但是导出后别人用了,就是这个意思。

也就是你定义了一个函数,但是并没有被入口函数使用,所以就在编译链接的时候干掉这些方法。再就是没有成为导出符号,也就是对于其他文件通过#import。这是对每个文件都生效的。

如果一个动态库也没有被主函数使用,也没有被导出符号。

image

意思一个动态库没有被主函数使用,也没有被导出符号,则移除这个动态库。链接信息剥离掉,默认不剥离。

image

为什么要加载.o,为什么要加载这个符号。

-noall_load 和 -all_load -> 链接器ld 加载静态库 -> App 没有用到静态库的代码,以类为最小单位,没有用到就不加载,如果是分类有时候是没办法判断用没用到,所以一下三方库建议我们使用-Objc,但是最好使用-force_load <file>,可以有效减少包体积。

6. 什么是tbd文件,在日常开发中有哪些应用场景?

tbd全称是text-based stub libraries,本质上就是一个YAML描述的文本文件。

他的作用是用于记录动态库的一些信息,包括导出的符号、动态库的架构信息、动态库的依赖信息

用于避免在真机开发过程中直接使用传统的dylib

对于真机来说,由于动态库都是在设备上,在Xcode上使用基于tbd格式的伪framework可以大大减少Xcode的大小。

tbd格式文件,本身是通过Xcode内置工具tapi-installapi专门来生成的,具体路径为:

/Applications/Xcode.app/Contents/Developer/Toolchains/XcodeDefaul t.xctoolchain/usr/bin/tapi installapi

7. 要减小APP的体积,应该使用静态库还是动态库,为什么?

一般使用静态库会减小APP体积。

静态库是.o文件的合集,在每个.o里面都包含了全局符号,.o多了就包含了多个全局符号,所以体积就大了。

动态库是最终的编译链接产物,所有符号都放在一起,减少了全局符号存储的次数,所以体积就小。

那么为什么还要使用静态库呢?因为静态库还存在一层编译连接的的过程,会将静态库合并到APP主程序文件中,可以优化,而动态库已经是编译链接的最终产物,还需要拷贝到frameworks文件夹中,所以会增加APP的体积。

其他

模仿生成APP的过程

.m -> .o .m -> .a 静态库 -> 链接去生成APP

静态库链接生成APP倒地存储在什么地方?

静态库的代码与主程序是放在一起的。

APP链接

  1. 找到头文件,api
  2. 找到库所在的位置
  3. 找到库的名称

1. 怎么判断什么场景使用动/静态库?
静态库:ipa体积小,不影响启动速度,但是静态库不能完全剥离符号,只允许剥离调试符号,静态库暴露出来的信息要多一些
动态库:资源文件更好处理,更加灵活,如果你不想暴露更多信息可以使用动态库,比如你是做SDK开发的。

2. 动态库超过6个?加载变慢怎么处理

1. 改成静态库
2. 动态库加载: execve Mach-O -> dyld -> load

3. 静态库符号冲突?
1. 使用-force_load指定两个冲突的静态库那个完全加载,那个由ld判断要加载的代码
2. 符号冲突,不叫同名符号就可以
1. 有源码,直接修改
2. 没有源码,objcopy->重命名一个符号
3. brew install llvm
4. --redefine-sym=old=new

4. all_load等只针对静态库

all_load只针对静态库,不针对动态库。

5. A静态库引用的B静态库,在项目中报找不到B中的符号?

A中只保存了B静态库的头文件,没有保存符号真正的实现代码,或者说没有保存符号真正代表的代码。
解决办法就是:

  1. 合并两个静态库
  2. 把B静态库也加载到APP中

6. 检测没有用到的代码(方法)?

个人觉得可以使用clang插桩,将用到的符号都检测出来,比如二进制重排的时候的order文件,然后对比所有符号。

或者参考上面这些dead strip等实现原理,做一些研究。

7. embed

只要是framework都可以embed,无关乎动/静态库

framework只是一种打包格式,里面可以包含一些资源文件。

8. hmap

.o -> 头文件目录/子目录 -> 特定的头文件 -> 花费一定的时间
hmap -> {特定的头文件:特定的头文件地址} -> 编译速度提升
特定的二进制结构

9. Two-level namespace

两级命名空间,默认的动态库是由两级命名空间的。

静态库为什么会符号冲突,就是静态库默认是取符号表找符号,所以两个同名符号就是会冲突。

Two-level namespace 动态库 -> 动态库 -> 符号,所以动态库的符号不会冲突。

source

最后编辑于
©著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 194,088评论 5 459
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 81,715评论 2 371
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 141,361评论 0 319
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 52,099评论 1 263
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 60,987评论 4 355
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 46,063评论 1 272
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 36,486评论 3 381
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 35,175评论 0 253
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 39,440评论 1 290
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 34,518评论 2 309
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 36,305评论 1 326
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 32,190评论 3 312
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 37,550评论 3 298
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 28,880评论 0 17
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 30,152评论 1 250
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 41,451评论 2 341
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 40,637评论 2 335

推荐阅读更多精彩内容