底层探寻alloc都发生了什么

简介: 有关alloc之后, 底层代码的执行顺序以及解析

有关alloc之后, 底层代码的执行顺序以及解析


微信图片_20220509100122.jpg

alloc流程图


  1. 从上面的流程图可以很清晰的看到alloc之后的执行方法顺序
  2. 最重要的就是最后的三个方法 instanceSizecalloc 以及obj->initInstanceIsa


  • instanceSize: 先计算出要开辟多大内存空间
  • calloc: 开辟内存空间, 申请内存, 返回地址指针
  • obj->initInstanceIsa: 关联到相应的类


以下放上源码参考:


static ALWAYS_INLINE id  
_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;  
    // 1:要开辟多少内存  
    size = cls->instanceSize(extraBytes);  
    if (outAllocatedSize) *outAllocatedSize = size;  
    id obj;  
    if (zone) {  
        obj = (id)malloc_zone_calloc((malloc_zone_t *)zone, 1, size);  
    } else {  
        // 2;怎么去申请内存  
        obj = (id)calloc(1, size);  
    }  
    if (slowpath(!obj)) {  
        if (construct_flags & OBJECT_CONSTRUCT_CALL_BADALLOC) {  
            return _objc_callBadAllocHandler(cls);  
        }  
        return nil;  
    }  
    // 3: ?
    if (!zone && fast) {  
        obj->initInstanceIsa(cls, hasCxxDtor);  
    } 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);  
}


  • 有关代码中的fastpathslowpath


//x很可能为真, fastpath 可以简称为 真值判断  
#define fastpath(x) (__builtin_expect(bool(x), 1))   
//x很可能为假,slowpath 可以简称为 假值判断  
#define slowpath(x) (__builtin_expect(bool(x), 0))


其中的__builtin_expect指令是由gcc引入的


  1. 目的:编译器可以对代码进行优化,以减少指令跳转带来的性能下降。即性能优化
  2. 作用:允许程序员将最有可能执行的分支告诉编译器。
  3. 指令的写法为:__builtin_expect(EXP, N)。表示 EXP==N的概率很大。
  4. fastpath定义中__builtin_expect((x),1)表示 x 的值为真的可能性更大;即 执行if 里面语句的机会更大
  5. slowpath定义中的__builtin_expect((x),0)表示 x 的值为假的可能性更大。即执行 else 里面语句的机会更大
  6. 在日常的开发中,也可以通过设置来优化编译器,达到性能优化的目的,设置的路径为:Build Setting --> Optimization Level --> Debug --> 将None 改为 fastest 或者 smallest


objc源码


访问参考

苹果开源源码汇总

更直接的地址


底层调试 (持续更新)


  1. 符号断点 (断点中增加 Symbolic Breakpoint, 然后增加要跟踪的函数名, 比如alloc, objc_alloc等内部函数名)
  2. 按住control + step into
  3. 汇编跟流程


微信图片_20220509100131.jpg

全局汇编断点



目录
相关文章
|
3月前
|
C++ 容器
【C++航海王:追寻罗杰的编程之路】关联式容器的底层结构——AVL树
【C++航海王:追寻罗杰的编程之路】关联式容器的底层结构——AVL树
34 5
|
3月前
|
存储 C#
揭秘C#.Net编程秘宝:结构体类型Struct,让你的数据结构秒变高效战斗机,编程界的新星就是你!
【8月更文挑战第4天】在C#编程中,结构体(`struct`)是一种整合多种数据类型的复合数据类型。与类不同,结构体是值类型,意味着数据被直接复制而非引用。这使其适合表示小型、固定的数据结构如点坐标。结构体默认私有成员且不可变,除非明确指定。通过`struct`关键字定义,可以包含字段、构造函数及方法。例如,定义一个表示二维点的结构体,并实现计算距离原点的方法。使用时如同普通类型,可通过实例化并调用其成员。设计时推荐保持结构体不可变以避免副作用,并注意装箱拆箱可能导致的性能影响。掌握结构体有助于构建高效的应用程序。
118 7
|
3月前
|
关系型数据库 C++ 容器
【C++航海王:追寻罗杰的编程之路】关联式容器的底层结构——红黑树
【C++航海王:追寻罗杰的编程之路】关联式容器的底层结构——红黑树
37 0
|
6月前
|
算法 数据库连接 程序员
深度剖析:C++内存池的设计与实现
深度剖析:C++内存池的设计与实现
429 0
|
6月前
深度解析指针与数组:探索内存管理的艺术
深度解析指针与数组:探索内存管理的艺术
70 0
|
6月前
|
Java 程序员 编译器
深度解剖动态内存管理
深度解剖动态内存管理
62 0
|
C++ 索引
19 深入理解数组:底层探究
深入理解数组:底层探究
75 0
|
缓存 C++
12-objc_msgSend底层调用流程探究
12-objc_msgSend底层调用流程探究
61 0
|
算法
【研究空间复用及函数调用问题】
但不是真正意义上的销毁,而是把使用该空间的权限还给操作系统,这片区域不再受你操控。
84 0
|
C++ iOS开发 Windows
手把手带你去分析NSObject本质是什么
这篇行文主要讲 NSObject 对象三连问:NSObject本质是什么,占用多少内存,以及怎么去分析。 从下图我们可以看到,我们平时编写的 Objective-C 代码,最终转换到机器语言的过程: https://img-blog.csdnimg.cn/2a6a930a8d3546f896d7527a95c3a576.png 换句话说,Objective-C的面向对象都是基于C\C++的数据结构实现的,或者说其底层实现其实都是C\C++代码。
178 0
手把手带你去分析NSObject本质是什么