-
常用指令
1. po: 为 print object 的缩写,显示对象的文本描述
2. bt: 打印函数的堆栈
3. register read 读取寄存器
4. x/nuf
n表示要显示的内存单元的个数
u表示一个地址单元的长度:
取值范围:
b 单字节
h 表示双字节
w 表示四字节
g 表示八字节
f表示显示方式:
取值范围:
x 按十六进制格式
d 按十进制格式
u 按十进制格式显示无符号
o 按八进制格式
t 按二进制格式
a 按十六进制格式
i 指令地址格式
c 按字符格式
f 按浮点数格式
持续更新中...
复制代码
-
创建一个熟悉的对象
**2022-04-16 18:14:47.784118+0800 SXObjcDebug[27806:312258] <NYPerson: 0x100b39ba0>-0x100b39ba0-0x7ff7bfeff310**
**2022-04-16 18:14:47.784578+0800 SXObjcDebug[27806:312258] <NYPerson: 0x100b39ba0>-0x100b39ba0-0x7ff7bfeff300**
**2022-04-16 18:14:57.634432+0800 SXObjcDebug[27806:312258] <NYPerson: 0x100b39ba0>-0x100b39ba0-0x7ff7bfeff308**
复制代码
通过调试代码,我们发现p1,p2,p3
都是打印内存0x100b39ba0
而&p1,&p2,&p3
打印的是不一样的。 我们通过objc4-838.1 看看alloc,init 做了什么。(也可以通过符号断点跟踪Symbolic Breakpoint
)
-
alloc的流程图
通过调试验证:
+ (id)alloc {
return _objc_rootAlloc(self);
}
id
_objc_rootAlloc(Class cls)
{
return callAlloc(cls, false/*checkNil*/, true/*allocWithZone*/);
}
复制代码
然后我们进入了objc_alloc (那么这边有一个问题,alloc里面调的是_objc_rootAlloc。这是为什么呢,我们一步一步来。)
callAlloc中 ((id(*)(id, SEL))objc_msgSend)(cls, @selector(alloc)) 消息转发到 alloc
static ALWAYS_INLINE id
callAlloc(Class cls, bool checkNil, bool allocWithZone=false)
{
#if __OBJC2__
if (slowpath(checkNil && !cls)) return nil;
if (fastpath(!cls->ISA()->hasCustomAWZ())) {
return _objc_rootAllocWithZone(cls, nil);
}
#endif
\
// No shortcuts available.
if (allocWithZone) {
return ((id(*)(id, SEL, struct _NSZone *))objc_msgSend)(cls, @selector(allocWithZone:), nil);
}
return ((id(*)(id, SEL))objc_msgSend)(cls, @selector(alloc));
}
复制代码
第二次到了callAlloc 中执行_objc_rootAllocWithZone->_class_createInstanceFromZone 最后在_class_createInstanceFromZone
进行内存分配。
-
_class_createInstanceFromZone分析
我们看到了_class_createInstanceFromZone 中计算内存的方法 size= cls->instanceSize(extraBytes);
我们跟踪到具体计算方法:
根据cpu位数是32位64位计算。
如:(8 + 7) & ~7 8字节对齐,取8的整数倍
(8 + 7) >> 3 << 3
0000 1001
&
1111 1000
0000 1000 = 8
复制代码
为什么是8位呢,用8字节取读不断变化的空间连续内存,空间换取时间。
-
通过struct 结构体分析内存对齐
下面我们通过计算 struct1,struct2,struct3 的字节数,验证字节对齐。
通过字节对齐算法,我们计算得出 struct1=24,struct2=16,struct3=48
验证输出:
总结
综上的现象,我们可知alloc()方法实现了对象的内存分配,内存对齐,将对象和类型绑定三个功能。
内存对齐实际案例
- Apple在64位下,对象内存对齐是16,结构体是8。
- 内存分配时,会根据属性或成员变量的类型length, 属性或成员的起始内存必须是该类型length的整数倍。