oc对象alloc源码分析

102 阅读2分钟

alloc 调用流程

添加符号断点

image.png

image.png

objc开源代码

开源地址:opensource.apple.com/tarballs/


1、libobjc.A.dylib`+[NSObject alloc]:
//step into instruction
2001-alloc&init探索`objc_alloc:
30x10d086c10 <+64>:  callq  0x10d0873d0; symbol stub for: objc_alloc
graph TD
下符号断点 --> 符号断点查看源码;
control-step-into --> 符号断点查看源码;
汇编查看 --> 符号断点查看源码;
graph LR
A[alloc] --> B(_objc_rootAlloc)
B --> C{callAlloc}
C --> |OBJC2宏| E(_objc_rootAllocWithZone)
C --> |不是OBJC2宏| D(objc_msgSend)
E --> F(_class_createInstanceFromZone)
graph LR
A[_class_createInstanceFromZone] --> B(cls->instanceSize)--> E(计算出内存空间大小)
A --> C[callAlloc] -->F[向系统申请开辟内存 返回地址指针]
A --> D(obj->initInstanceIsa)-->G[关联到相应的类]

//方法1 要开辟多少内存
size = cls->instanceSize(extraBytes);
//内存对齐
/**
 8 + 15 = 23
 16 + 7
 0000 0000 0001 0111 23
 1111 1111 1111 0000 15的取反
 0000 0000 0001 0000 16倍数
 **/

static inline size_t align16(size_t x) {
    return (x + size_t(15)) & ~size_t(15);
}

init

+ (id)init {
 return** (id)self; //工厂设计方法,做一些数据初始化,提供构造方法入口
}

new

+ (id)new {
    return [callAlloc(self, false/*checkNil*/) init];
}

new使用上没有区别,存在不同的点: 使用类可能通过重写init方法,做其他数据的的初始化,使用new无法调用init构造方法

对象内存结构探索

TGPerson *objc1 = [TGPerson alloc];
objc1.name      = @"TAN";
objc1.nickName  = @"KE";

=========输出结果=============
(lldb) x objc1
0x10065eee0:fd21000001801d001010000001000000
0x10065eef0:30100000010000000000000000000000

(lldb) x/4gx objc1
0x10065eee0: 0x001 d8001000021fd 0x0000000100001010
0x10065eef0: 0x0000000100001030 0x0000000000000000
(lldb) po 0x0000000100001010
TAN
(lldb) po 0x0000000100001030
KE

x/4gx p

x /nuf <addr>
n表示要显示的内存单元的个数
v
u表示一个地址单元的长度:
b表示单字节
h表示双字节
w表示四字节
g表示八字节.
f表示显示方式,可取如下值:
x按十六进制格式显示变量
d按十进制格式显示变量
u按十进制格式显示无符号整型
o按八进制格式显示变量
t按二进制格式显示变量
a按十六进制格式显示变量
i指令地址格式
C按字符格式显示变量
f按浮点数格式显示变量  //p/f 打印16进制的浮点类型

LLVM编译器优化

编译器优化设置

image.png