alloc&init原理探索

2020-01-07  本文已影响0人  TRACER_
一、调试方法:

开篇我们先来介绍三种可以进入libobjc.A.dylib(objc_alloc所在的动态库)的调试方法,需要用真机进行调试:

1、直接下断点:断点在Person *p1 = [Person alloc];行 -> 按住control -> 点击 step into进入;

下断点

2、符号断点:

符号断点

3、通过汇编查看:断点在Person *p1 = [Person alloc];行,开启Always Show Disassembly,如图:

汇编方式
二、接下来我们看一段代码:
Person *p1 = [Person alloc];
Person *p2 = [p1 init];
Person *p3 = [p1 init];
NSLog(@"�%@ - %p",p1,&p1);
NSLog(@"�%@ - %p",p2,&p2);
NSLog(@"�%@ - %p",p3,&p3);

打印结果如下:

�<Person: 0x600003885d40> - 0x7ffeec2e10c8
�<Person: 0x600003885d40> - 0x7ffeec2e10c0
�<Person: 0x600003885d40> - 0x7ffeec2e10b8

以上我们可以看出p1、p2、p3三个不同的指针指向的是同一片内存空间,init大概貌似啥也没干。

三、下面我们详细看一下初始化对象时常用的alloc/init/new都做了些啥?

准备工作:源码下载及配置

1、 alloc探索

1) 流程图:

alloc流程图.png

2) 理解:

3) 分支流程:

a、 hasCustomAWZ():判断当前方法是否有默认的allocWithZone
b、canAllocFast():这里最终直接返回false,顺着源码具体分析一下:

bool canAllocFast() {
       assert(!isFuture());
       return bits.canAllocFast();
}
#if FAST_ALLOC
   // 省略代码

    bool canAllocFast() {
        return bits & FAST_ALLOC;
    }
#else
    // 省略代码
   // 一般会走这里
    bool canAllocFast() {
        return false;
    }
#endif
#if !__LP64__
// .....
#elif 1
// .....
// 一般会走这里
#else
// .....
#define FAST_ALLOC              (1UL<<2)

#endif

c、来到_class_createInstanceFromZone中:

//  字节对齐:至少16字节
size_t instanceSize(size_t extraBytes) {
        size_t size = alignedInstanceSize() + extraBytes;
        // CF requires all objects be at least 16 bytes.
        if (size < 16) size = 16;
        return size;
    }

2、init探索
这里可以看到返回的是alloc中创建的obj,主要作用是预留给开发者在工厂模式中重写初始化方法,方便自定义以及扩展。

+ (id)init {
    return (id)self;
}

3、new探索

+ (id)new {
    return [callAlloc(self, false/*checkNil*/) init];
}
四、LLDB命令

如有不当,欢迎指正,感谢。

上一篇 下一篇

猜你喜欢

热点阅读