alloc原理

316 阅读2分钟

指针和内存

1.1 测试代码

    YGPerson *p1 = [YGPerson alloc];
    YGPerson *p2 = [p1 init];
    YGPerson *p3 = [p1 init];
    NSLog(@"%@-%p-%p",p1,p1,&p1);
    NSLog(@"%@-%p-%p",p2,p2,&p2);
    NSLog(@"%@-%p-%p",p3,p3,&p3);
  1. 通过alloc创建一个p1对象
  2. 再通过初始化方法创建 p2 和 p3

1.2 查看和总结

日志打印情况如下:

  • p1, p2, p3 对象内存地址都是 0x600001ccc500
  • 他们对应的指针地址不同 分别是 0x7ffeec8080a80x7ffeec8080a00x7ffeec808098
  • 指针地址存放放在栈空间

alloc流程

1.1 探索方式

  1. Control+Step into

  2. Debug-Degworkflow-Always show disassembly

    • 先汇编调试
    • 找到对应的方法
    • 然后在通过添加符号方法断点的方法调试
  3. 符号断点 直接添加方法符号 通过添加Symbolic Breakpoint...

    • alloc
    • objc_alloc

1.2 源码地址

1.3 编译器优化

    int lgSum(int a, int b){
        return a+b;
    }
    ​
    int main(int argc, char * argv[]) {
        int a = 10;
        int b = 20;
        int c = lgSum(a, b);
        return 0;
    }
  1. 第一次执行通过汇编可以 调用 lgSum方法和寄存器之间的值的传递和计算
  2. 通过x0或者w0寄存器可以得出 C的值
  3. 当再次运行 汇编语言中 找不到lgSub方法 被优化掉

1.4 alloc流程图

先大致看一下alloc流程图

1.5 allo,objc_alloc

    NSObject.mm
    ​
    // Calls [cls alloc].
    id
    objc_alloc(Class cls)
    {
        return callAlloc(cls, true/*checkNil*/, false/*allocWithZone*/);
    }
    ​
    + (id)alloc {
        return _objc_rootAlloc(self);
    }
    ​
  1. 最初汇编调试会执行 objc_alloc 但是源码调试点进去alloc 却是执行NSObject 的alloc类方法
  2. 断点到objc_alloc 会先执行这里 在执行 alloc方法
  3. 上面那个图可以看出先走 objc_alloc

1.6 alloc核心方法

  1. _objc_rootAllocWithZone(cls, nil);

    • callAlloc中的方法会执行两遍
  2. _class_createInstanceFromZone

  3. cls->instanceSize

    • 计算需要内存空间的大小
  4. calloc

    • 向系统申请开辟内存,返回地址指针
  5. initInstanceIsa

    • 关联到相应的类

    objc_alloc 和alloc都执行过calloc

    1.这是llvm对alloc的优化进行标记

字节对齐

1.1 字节对齐算法

计算所需要的内存空间的时候会用到

uint32_t alignedInstanceStart() const {
        return word_align(unalignedInstanceStart());
        }

        //通过算法 进行字节对齐 8字节对齐  #   define WORD_MASK 7UL
        static inline uint32_t word_align(uint32_t x) {
        return (x + WORD_MASK) & ~WORD_MASK;
        }
  1. unalignedInstanceStart 获取到成员变量的内存大小

    • 如果什么变量都没有 就一个isa指针 8字节
  2. word_align 8字节对齐

1.2 成员变量为什么8字节对齐

为什么不用 4字节或者16字节

  1. cpu读取内存的时候用固定的宽度 增加读取速度
  2. 但会造成空间浪费
  3. 基本上8字节是最大的字节
  4. 如果用16字节会造成更多空间浪费
  5. 合理的用空间换取时间