OC底层原理03- alloc底层探索

前言

上一篇文章我们研究的对象的内存

总结一下内存

LGPerson *person = [LGPerson alloc];
1.sizeof(person): 该运算符只是返回类型的大小,而非实际的内存 因为isa结构体指针占用8字节

2.class_getInstanceSize([LGPerson class]):传入一个类对象,返回一个对象的实例至少需要多少内存,需要导入#import <objc/runtime.h>, 内存8字节对齐

3.malloc_size((__bridge const void *)(person)): 返回系统实际分配的内存大小,需要导入#import <malloc/malloc.h>,内存16字节对齐

下面我们研究一下对象的本质 对象的本质的是什么呢

一.对象的本质

1.clang是什么?

Clang是⼀个C语⾔、C++Objective-C语⾔的轻量级编译器。源代码发布于BSD协议下。
Clang将⽀持其普通lambda表达式、返回类型的简化处理以及更好的处理constexpr关键字。

Clang是⼀个由Apple主导编写,基于LLVMC/C++/Objective-C编译器

2013年4⽉,Clang已经全⾯⽀持C++11标准,并开始实现C++1y特性(也就是C++14,这是
C++的下⼀个⼩更新版本)。Clang将⽀持其普通lambda表达式、返回类型的简化处理以及更好的处理constexpr关键字。

Clang是⼀个C++编写、基于LLVM、发布于LLVM BSD许可证下的C/C++/Objective-C/
Objective-C++编译器。它与GNU C语⾔规范⼏乎完全兼容(当然,也有部分不兼容的内容,包括编译命令选项也会有点差异),并在此基础上增加了额外的语法特性,⽐如C函数重载
(通过__attribute__((overloadable))来修饰函数),其⽬标(之⼀)就是超越GCC

2.clang使用

clang -rewrite-objc main.m -o main.cpp 把⽬标⽂件编译成C++⽂件

UIKit报错问题

clang -rewrite-objc -fobjc-arc -fobjc-runtime=ios-13.0.0 -isysroot / Applications/Xcode.app/Contents/Developer/Platforms/ iPhoneSimulator.platform/Developer/SDKs/iPhoneSimulator13.0.sdk main.m

xcode安装的时候顺带安装了xcrun命令,xcrun命令在clang的基础上进⾏了
⼀些封装,要更好⽤⼀些

xcrun -sdk iphonesimulator clang -arch arm64 -rewrite-objc main.m -o main-arm64.cpp (模拟器)

xcrun -sdk iphoneos clang -arch arm64 -rewrite-objc main.m -o mainarm64.cpp (⼿机)

3.clang搞一下

进入项目main文件夹 添加XWTest对象如下图
Xnip2021-06-11_19-41-25.jpg

通过终端进入项目 执行 clang -rewrite-objc main.m -o main.cpp 生成 main.cpp文件

Xnip2021-06-11_19-40-05.jpg

查看main.cpp文件源码 对象在底层的本质就是结构体 全局搜索XWTest找到这里 如下图所示

Xnip2021-06-11_19-51-42.jpg

全局搜索NSObject_IMPL 是我们熟知的isa

Xnip2021-06-11_19-50-08.jpg

对象的本质是objc_object类型
Xnip2021-06-11_19-55-13.jpg

id person 我们平时为什么这么写

Xnip2021-06-11_19-59-52.jpg

通过获取对象的首地址进行偏移进行get取值 set赋值的操作

Xnip2021-06-11_20-01-35.jpg

二.位域

1.位域优化内存 例如:front:1 代表front占用1位

Xnip2021-06-11_20-25-11.jpg
2.联合体互斥 结构体共存

Xnip2021-06-11_20-36-00.jpg

结构体(struct)中所有变量是“共存”的——优点是“有容乃⼤”,
全⾯;缺点是struct内存空间的分配是粗放的,不管⽤不⽤,全分配。
联合体(union)中是各变量是“互斥”的——缺点就是不够“包容”; 逻辑教育
但优点是内存使⽤更为精细灵活,也节省了内存空间

三.nonPointerIsa的分析

我们平时用的类也是指针 8字节*8 = 64位 大大的浪费了空间 苹果优化了一下 是否正在释放 引用计数 weak 关联对象 析构函数
要看位域 回到我们alloc 最后一步对象和指针地址进行绑定

Xnip2021-06-11_22-34-27.jpg
进入到initIsa

Xnip2021-06-11_22-34-36.jpg

进入到initIsa

Xnip2021-06-11_22-34-58.jpg

进入到isa_t

Xnip2021-06-11_22-35-16.jpg

点击进入

Xnip2021-06-11_22-35-32.jpg

nonpointer:表示是否对 isa 指针开启指针优化
0:纯isa指针,1:不⽌是类对象地址,isa 中包含了类信息、对象的引⽤计数等

has_assoc:关联对象标志位,0没有,1存在

has_cxx_dtor:该对象是否有 C++ 或者 Objc 的析构器,如果有析构函数,则需要做析构逻辑,
如果没有,则可以更快的释放对象

shiftcls: 存储类指针的值。开启指针优化的情况下,在 arm64 架构中有 33 位⽤来存储类指针

magic:⽤于调试器判断当前对象是真的对象还是没有初始化的空间

weakly_referenced:志对象是否被指向或者曾经指向⼀个 ARC 的弱变量,
没有弱引⽤的对象可以更快释放。

deallocating:标志对象是否正在释放内存

has_sidetable_rc:当对象引⽤技术⼤于 10 时,则需要借⽤该变量存储进位

extra_rc:当表示该对象的引⽤计数值,实际上是引⽤计数值减 1,
例如,如果对象的引⽤计数为 10,那么 extra_rc 为 9。如果引⽤计数⼤于 10,
则需要使⽤到下⾯的 has_sidetable_rc

四.isa推到class

对象的首地址&掩码地址得到类的地址、
掩码地址:define ISA_MASK 0x00007ffffffffff8ULL
Xnip2021-06-11_22-56-58.jpg

四.isa的位运算

Xnip2021-06-11_23-12-11.jpg

© 版权声明
THE END
喜欢就支持一下吧
点赞0 分享