iOS底层iOS深入原理

iOS底层--对象原理解析

2021-07-16  本文已影响0人  iOS心安

学习资料

指针地址和内存地址

YYObjet *p1 = [YYObjet alloc];
YYObjet *p2 = [p1 init];
YYObjet *p3 = [p1 init];
YYObjet *p4 = [YYObjet alloc];

NSLog(@"%@-%p-%p",p1,p1,&p1);
NSLog(@"%@-%p-%p",p2,p2,&p2);
NSLog(@"%@-%p-%p",p3,p3,&p3);
NSLog(@"%@-%p-%p",p4,p4,&p4);

<YYObjet: 0x6000025ec780>-0x6000025ec780-0x7ffeef1a1068
<YYObjet: 0x6000025ec780>-0x6000025ec780-0x7ffeef1a1060
<YYObjet: 0x6000025ec780>-0x6000025ec780-0x7ffeef1a1058
<YYObjet: 0x6000025ec7b0>-0x6000025ec7b0-0x7ffeef1a1050

复制代码

通过对比得到:

alloc 开辟内存空间,init 并没有开辟内存的操作,通过init的源码可以直观的看的出来。

底层探索的三种方法

1.符号断点

操作步骤

Jun-20-2021 12-02-53.gif image.png Jul-13-2021 11-22-33.gif

得到结果

image.png

2.汇编

Jun-20-2021 10-04-34.gif

3.符号断点 确定未知

Jul-13-2021 11-30-37.gif

得到结果

image.png

通过以上三种调试方式,断点断在libobjc.A.dylib。可以在苹果开源网站下载对应的开源源码,对应的配置流程工程网上也有很多,可以下载调试[开车链接],更多的关注alloc的创建流程。

alloc 创建流程

通过流程跟踪,发现最终调用了 _class_createInstanceFromZone

[图片上传失败...(image-a4807f-1626418940051)]

可以用流程图更加清晰的表达

未命名文件 (2).png

_class_createInstanceFromZone

_class_createInstanceFromZone(Class cls, size_t extraBytes, void *zone,
                              int construct_flags = OBJECT_CONSTRUCT_NONE,
                              bool cxxConstruct = true,
                              size_t *outAllocatedSize = nil)
{
    ASSERT(cls->isRealized());

    // Read class's info bits all at once for performance
    bool hasCxxCtor = cxxConstruct && cls->hasCxxCtor();
    bool hasCxxDtor = cls->hasCxxDtor();
    bool fast = cls->canAllocNonpointer();
    size_t size;

    size = cls->instanceSize(extraBytes); //计算内存大小(编译时期)
    if (outAllocatedSize) *outAllocatedSize = size;

    id obj;
    if (zone) {
        obj = (id)malloc_zone_calloc((malloc_zone_t *)zone, 1, size);
    } else {
        obj = (id)calloc(1, size); //开辟内存空间
    }
    if (slowpath(!obj)) {
        if (construct_flags & OBJECT_CONSTRUCT_CALL_BADALLOC) {
            return _objc_callBadAllocHandler(cls);
        }
        return nil;
    }

    if (!zone && fast) {
        obj->initInstanceIsa(cls, hasCxxDtor);//初始化isa和cls绑定
    } else {
        // Use raw pointer isa on the assumption that they might be
        // doing something weird with the zone or RR.
        obj->initIsa(cls);
    }

    if (fastpath(!hasCxxCtor)) {
        return obj;
    }

    construct_flags |= OBJECT_CONSTRUCT_FREE_ONFAILURE;
    return object_cxxConstructFromClass(obj, cls, construct_flags);
}
复制代码
inline size_t instanceSize(size_t extraBytes) const {
        if (fastpath(cache.hasFastInstanceSize(extraBytes))) {
            return cache.fastInstanceSize(extraBytes);
        }
        // 计算大小
        size_t size = alignedInstanceSize() + extraBytes;
        // CF requires all objects be at least 16 bytes.
        if (size < 16) size = 16;// 十六字节对齐
        return size;
    }
复制代码
  size_t fastInstanceSize(size_t extra) const
    {
        ASSERT(hasFastInstanceSize(extra));

        if (__builtin_constant_p(extra) && extra == 0) {
            return _flags & FAST_CACHE_ALLOC_MASK16;
        } else {
            size_t size = _flags & FAST_CACHE_ALLOC_MASK; 
            // remove the FAST_CACHE_ALLOC_DELTA16 that was added
            // by setFastInstanceSize
            return align16(size + extra - FAST_CACHE_ALLOC_DELTA16); //字节对齐
        }
    }
复制代码
static inline size_t align16(size_t x) {
    return (x + size_t(15)) & ~size_t(15);
}

以10为例:
align16(10){
    =(10 + size_t(15)) & ~size_t(15) 
    =(10 + 15)& ~ 15
    = 25 & ~ 15
    = 11001 & ~ 01111 //转化为二进制
    = 11001 & 10000
    = 10000 (十进制:16)
}


转载

上一篇下一篇

猜你喜欢

热点阅读