底层探寻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

全局汇编断点



目录
相关文章
|
运维 负载均衡 网络协议
从底层技术来看,GSLB 究竟难在哪儿
本文作者吕宏利来自硅谷的SRE,有着多年的国内外大型互联网公司运维开发经验,专注于分布式系统设计、监控、容量规划,数据中心技术以及生产环境的最佳实践。在本文中他将他将向读者介绍什么是GSLB,以及实现细节和维护方法。
7866 0
|
2月前
|
存储 C++ 索引
【C++】C++STL 揭秘:Strng背后的底层逻辑(二)
【C++】C++STL 揭秘:Strng背后的底层逻辑
|
2月前
|
C++
【C++】C++STL 揭秘:Strng背后的底层逻辑(三)
【C++】C++STL 揭秘:Strng背后的底层逻辑
|
2月前
|
编译器 Serverless C++
【C++】C++STL 揭秘:Strng背后的底层逻辑(一)
【C++】C++STL 揭秘:Strng背后的底层逻辑
|
4月前
|
存储 C#
揭秘C#.Net编程秘宝:结构体类型Struct,让你的数据结构秒变高效战斗机,编程界的新星就是你!
【8月更文挑战第4天】在C#编程中,结构体(`struct`)是一种整合多种数据类型的复合数据类型。与类不同,结构体是值类型,意味着数据被直接复制而非引用。这使其适合表示小型、固定的数据结构如点坐标。结构体默认私有成员且不可变,除非明确指定。通过`struct`关键字定义,可以包含字段、构造函数及方法。例如,定义一个表示二维点的结构体,并实现计算距离原点的方法。使用时如同普通类型,可通过实例化并调用其成员。设计时推荐保持结构体不可变以避免副作用,并注意装箱拆箱可能导致的性能影响。掌握结构体有助于构建高效的应用程序。
126 7
|
7月前
|
存储 算法 C语言
结构体:编程之基石
结构体:编程之基石
|
7月前
|
算法 数据库连接 程序员
深度剖析:C++内存池的设计与实现
深度剖析:C++内存池的设计与实现
455 0
|
C++ 索引
19 深入理解数组:底层探究
深入理解数组:底层探究
75 0
|
缓存 C++
12-objc_msgSend底层调用流程探究
12-objc_msgSend底层调用流程探究
64 0
|
存储 算法
嵌入式ARM设计编程(一) 简单数据搬移
嵌入式ARM设计编程(一) 简单数据搬移
80 0
嵌入式ARM设计编程(一) 简单数据搬移