美文网首页
一、alloc&init探索

一、alloc&init探索

作者: 顺7zi燃 | 来源:发表于2020-09-06 17:32 被阅读0次

objc源码官方地址
分析源码,先从创建对象开始

    LGPerson *p1 = [LGPerson alloc];
    LGPerson *p2 = [p1 init];
    LGPerson *p3 = [p1 init];
    //输出 内容、内存地址、指针地址
    LGNSLog(@"%@ - %p - %p",p1,p1,&p1);
    LGNSLog(@"%@ - %p - %p",p2,p2,&p2);
    LGNSLog(@"%@ - %p - %p",p3,p3,&p3);

打印结果:
<LGPerson: 0x6000028bcb40> - 0x6000028bcb40 - 0x7ffee41000e8
<LGPerson: 0x6000028bcb40> - 0x6000028bcb40 - 0x7ffee41000e0
<LGPerson: 0x6000028bcb40> - 0x6000028bcb40 - 0x7ffee41000d8
alloc.png

1、alloc做了什么?
开辟内存空间
2、init做了什么?

//init 没有对空间做任何修改
+ (id)init {
    return (id)self;
}

3、new做了什么?

+ (id)new {
    return [callAlloc(self, false) init];
}  
// 等同于 (alloc + init)
//不建议直接new, 因为可能会重写 init ,init 可能会带参数

4、alloc怎么开辟空间的?
主要是 _class_createInstanceFromZone 的实现流程,分三步:
cls->instanceSize :计算需要的内存空间大小(16字节对齐)
calloc :向系统申请开辟内存,返回地址指针
obj->initInstanceIsa:将类和内存地址绑定在一起,实例的isa指向类

5、alloc 的流程图

alloc源码流程图.png

6、栈内存 是连续的?
栈内存是连续的,一个对象是8字节

7、NSObject *objc = [NSObject alloc] 为什么没有进+ (id)alloc {..}方法?

NSObject.mm
//LLVM (编译启动): 任何级别调用的alloc方法,都会调用到objc_alloc方法
// Calls [cls alloc].
id objc_alloc(Class cls)
{
    return callAlloc(cls, true/*checkNil*/, false/*allocWithZone*/);
}

扩展:
1、命令
bt:打印堆栈
x 地址: 查看当前地址的内存情况
x/4gx 地址: 以16进制的形式打印4个地址
x/8gx 地址: 以16进制的形式打印8个地址
po 变量:显示内存的内容

2、字节对齐

//字节对齐算法, 16的倍数
//1.方便速度便捷,2. 16更安全
static inline size_t align16(size_t x) {
    return (x + size_t(15)) & ~size_t(15);
}

任何一个对象都有一个isa ,isa 占8字节,如果按8字节对齐,每个对象都紧诶着其他对象的isa,会容易出现混乱, 为了内存安全,预留空间。 为什么是16?一个对象8字节,以最小单元翻倍。因为如果以一个9或10就会很恶心,需要随时改变读取的长度。每次都按8或16来读,每次都读这么多,不会产生混乱。

3、看源码的3种方式

  • 下符号断点
    第一步:在[LGPerson alloc]加断点,并运行
    第二步:下符号断点


    第一步:[LGPerson alloc]加断点.png
第二步:下符号断点的位置.png 符号断点.png 结果:alloc所在的库.png
  • control + (step into)
    第一步:在[LGPerson alloc]加断点
    第二步:control + (step into)
    第三步:下符号断点


    第二步:control + (step into).gif
第三步:添加符号断点objc_alloc.png
  • 最常用方法:汇编查看流程
    第一步:在[LGPerson alloc]加断点
    第二步:debug ->debug workflow -> always show assembly
    第三步:下符号断点


    第二步:打开汇编查看.png
第三步:添加objc_alloc符号断点.png

相关文章

  • isa的初始化&指向分析

    在探索alloc&init一篇中,我们对alloc&init有了初步的了解,其中包括对isa的初始化,本篇我们进一...

  • 一、alloc&init探索

    objc源码官方地址分析源码,先从创建对象开始 1、alloc做了什么?开辟内存空间2、init做了什么? 3、n...

  • alloc&init探索

    OC底层原理学习 alloc 初探 首先创建一个继承于NSObject的Person类带着以下几个疑问,查看打印结...

  • alloc&init探索

    main函数的加载流程 1.在int main前面打个断点 然后增加一个_objc_init的符号断点 记得关闭左...

  • alloc&init 探索

    alloc&init 探索 首先要明确alloc做了什么,init做了什么。 上方的p1/p2/p3经打印是一模一...

  • iOS 底层探索 文章汇总

    一、alloc&init探索[https://www.jianshu.com/p/d6833d5d8b09]二、i...

  • alloc&init底层探索

    [[NSObject alloc] init]两段式构造 1.对象分配,方法有alloc何allocWithZon...

  • alloc&init原理探索

    一、调试方法: 开篇我们先来介绍三种可以进入libobjc.A.dylib(objc_alloc所在的动态库)的调...

  • iOS-OC对象原理_alloc&init

    alloc&init探索 NSLog结果: 用图表示大概是这个样子: 表示我是谁(我在栈上的位置), 表示我指向的...

  • OC底层-alloc&init探索

    前言 我们创建一个对象经常用到alloc、init或者new,也大概知道alloc做了分配内存,init做了初始化...

网友评论

      本文标题:一、alloc&init探索

      本文链接:https://www.haomeiwen.com/subject/vjfcektx.html