区块链技术博客
www.b2bchain.cn

alloc 底层原理求职学习资料

本文介绍了alloc 底层原理求职学习资料,有助于帮助完成毕业设计以及求职,是一篇很好的资料。

对技术面试,学习经验等有一些体会,在此分享。

在 iOS 开发中,创建对象的时候,经常会用到一个函数alloc,所以今天就探索下 alloc 的底层原理,俗话说工欲善其事必先利其器,下面我们介绍下,探索底层的东西,需要的一些基本准备东西。

准备工作

  • 1: objc是探索底层原理的一个重要工具,我们可以通过苹果开源的东西,去了解他的设计理念以及程序运行的流程,目前最新的是objc4-824,我的设备上运行起来的是objc4-818.2

  • 2: 肯定是对 iOS 开发有所了解了,起码得有 iOS 实际开发经验最少也得半年或者一年以上吧。

  • 3: 手头有一台 Mac 电脑,Mac 电脑上安装 Xcode。

  • 4: 具体objc源码配置问题可以找到 我的Github地址中查看缺少文件以及报错问题。

一.学习线索

我们平时的开发中都会认为main函数是应用程序的入口,是否是这样的?我们在 main函数 的入口添加一个断点。bt查看运行的堆栈信息,发现一些端倪!

alloc 底层原理

发现在main函数之前还有一个start,并且这个start来自动态库libdyld.dylid。说明 main函数 并不是应用程序的入口,在此之前还有一些应用程序启动过程。
很陌生,我们先从简单的开始,在这里添加一个符号断点alloc,过掉main函数入口的断点,bt查看堆栈信息,可以发现更多程序加载内容。

alloc 底层原理

比如UIKitCoreCoreFoundationlibdispach.dylib等等,我们开发过程中最常用的比如UI、NSObject、GCD等内容,均是来自这些库。

先从最熟悉的创建对象开始!!!

二.alloc原理初探

开发过程中创建对象是我们最常写的代码。
GFPerson * gf = [[GFPerson alloc] init];
留下一个问题,这里alloc做了什么,init又做了什么呢?

  • 2.1.探索案例

引入一个案例,使用 alloc方法 初始化一个对象gf1,通过gf1调用 init方法创建了 gf2gf3,然后分别输出对象、对象地址、指针地址。

alloc 底层原理

根据运行结果,发现三者的对象输出是一样的,对象地址也是一样的,指针地址不一样。
案例总结:

  • a: 三个指针指向了同一个对象,这个对象是<GFPerson: 0x600000fbc1f0>;
  • b: 三个指针的地址是连续的存储在栈区中,并且从高位向低位开辟内存空间;

alloc 底层原理

  • c: 指针占用空间是8个字节;
  • d: lg1通过alloc方法开辟了内存空间,创建了对象;通过init方法初始化lg2lg3并没有开辟内存空间,也就是没有创建对象。

那么,alloc是如何开辟内存空间创建对象的呢?init又起到什么作用呢?

  • 2.2.底层探究方法

在我们的开发工程中,Jump to Definition只能看到alloc方法的声明,不能看到真正的源码实现流程。

+ (instancetype)alloc OBJC_SWIFT_UNAVAILABLE("use object initializers instead");

下面提供三种底层探究的方法。

  • 2.2.1. 添加符号断点的形式直接跟流程

我们要研究alloc方法,那就添加个符号断点alloc。符号断点添加方式见下图:

alloc 底层原理

因为我们暂时只研究GFPerson类的初始化流程,所以避免其他类调用alloc导致的干扰,运行时先将alloc断点设置为Disable Breakpoint。在程序运行到GFPerson * gf1 = [GFPerson alloc];时,再将alloc断点设置为Enable Breakpoint。运行结果见下图:

alloc 底层原理

根据上图的内容发现,[GFPerson alloc]最终走到了+[NSObject alloc];为什么是NSObject呢?因为LGPerson继承自NSObject,子类中没有alloc方法,最终会调用父类的alloc方法

并且我们还发现了一个重要线索,[NSObject alloc]来自于libobjc.A.dylib动态库。

  • 2.2.2. 通过按住 control - step into

在GFPerson * gf1 = [GFPerson alloc];这行代码添加断点,运行程序,运行到断点后,点击control – step into。操作流程见下图:

alloc 底层原理

进入后发现调用了objc_alloc,接着采用方式1添加符号断点objc_alloc,运行程序。

alloc 底层原理

同样我们也发现了一个重要线索,objc_alloc也来自于libobjc.A.dylib动态库。

  • 2.2.3. 汇编查看跟流程

设置方式:Debug -> Debug Workflow -> Always Show Disassembly。

alloc 底层原理

GFPerson * gf1 = [GFPerson alloc];这行代码添加断点,运行程序。进入汇编流程,见下图:

alloc 底层原理

看不懂汇编,但是根据关键字眼也是可以发现一些端倪的,比如同样会走到objc_alloc方法,继续采用符号断点方式查找出处。

alloc 底层原理

  • 2.2.4.探索总结

alloc 底层原理

根据上面的探索方式我们找到了alloc方法的出处,也就是动态库:libobjc.A.dylib
同时也有个疑问,初始化调用了alloc方法,但在上面的汇编跟踪发现会调用objc_alloc方法,这两个方法又有什么关系呢?
如果要深入学习alloc的实现流程,下载源码objc4源码。源码下载地址:objc4源码下载地址

三.结合源码分析alloc

源码下载完成,采用关键字alloc 全局搜索,在 NSObject.mm文件(Objective-C++汇编)中找到alloc的方法实现。

  • 1.alloc的流程分析

根据上面搜索的alloc方法实现,跟踪关键源码如下:

// alloc + (id)alloc {     return _objc_rootAlloc(self); }  // _objc_rootAlloc id _objc_rootAlloc(Class cls) {     return callAlloc(cls, false/*checkNil*/, true/*allocWithZone*/); }  // callAlloc static ALWAYS_INLINE id callAlloc(Class cls, bool checkNil, bool allocWithZone=false) { #if __OBJC2__     if (slowpath(checkNil && !cls)) return nil;     if (fastpath(!cls->ISA()->hasCustomAWZ())) {         return _objc_rootAllocWithZone(cls, nil);     } #endif      // No shortcuts available.     if (allocWithZone) {         return ((id(*)(id, SEL, struct _NSZone *))objc_msgSend)(cls, @selector(allocWithZone:), nil);     }     return ((id(*)(id, SEL))objc_msgSend)(cls, @selector(alloc)); }  // _objc_rootAllocWithZone id _objc_rootAllocWithZone(Class cls, malloc_zone_t *zone __unused) {     // allocWithZone under __OBJC2__ ignores the zone parameter     return _class_createInstanceFromZone(cls, 0, nil,                                          OBJECT_CONSTRUCT_CALL_BADALLOC); }

从源码可以得到如下流程:

alloc 底层原理

如何验证callAlloc走的是_objc_rootAllocWithZone还是objc_msgSend呢?没错上面已经学习了探索方式,这里可以使用汇编+添加符合断点!

下面设置符号断点,在程序运行到GFPerson * gf1 = [GFPerson alloc];之后再将符号断点设置为Enable Breakpoint,确保跟踪的是GFPerson的初始化流程。断点调试,发现走的是_objc_rootAllocWithZone的流程。

alloc 底层原理

在 iOS 开发中,创建对象的时候,经常会用到一个函数alloc,所以今天就探索下 alloc 的底层原理,俗话说工欲善其事必先利其器,下面我们介绍下,探索底层的东西,需要的一些基本准备东西。

准备工作

  • 1: objc是探索底层原理的一个重要工具,我们可以通过苹果开源的东西,去了解他的设计理念以及程序运行的流程,目前最新的是objc4-824,我的设备上运行起来的是objc4-818.2

  • 2: 肯定是对 iOS 开发有所了解了,起码得有 iOS 实际开发经验最少也得半年或者一年以上吧。

  • 3: 手头有一台 Mac 电脑,Mac 电脑上安装 Xcode。

  • 4: 具体objc源码配置问题可以找到 我的Github地址中查看缺少文件以及报错问题。

一.学习线索

我们平时的开发中都会认为main函数是应用程序的入口,是否是这样的?我们在 main函数 的入口添加一个断点。bt查看运行的堆栈信息,发现一些端倪!

alloc 底层原理

发现在main函数之前还有一个start,并且这个start来自动态库libdyld.dylid。说明 main函数 并不是应用程序的入口,在此之前还有一些应用程序启动过程。
很陌生,我们先从简单的开始,在这里添加一个符号断点alloc,过掉main函数入口的断点,bt查看堆栈信息,可以发现更多程序加载内容。

alloc 底层原理

比如UIKitCoreCoreFoundationlibdispach.dylib等等,我们开发过程中最常用的比如UI、NSObject、GCD等内容,均是来自这些库。

先从最熟悉的创建对象开始!!!

二.alloc原理初探

开发过程中创建对象是我们最常写的代码。
GFPerson * gf = [[GFPerson alloc] init];
留下一个问题,这里alloc做了什么,init又做了什么呢?

  • 2.1.探索案例

引入一个案例,使用 alloc方法 初始化一个对象gf1,通过gf1调用 init方法创建了 gf2gf3,然后分别输出对象、对象地址、指针地址。

alloc 底层原理

根据运行结果,发现三者的对象输出是一样的,对象地址也是一样的,指针地址不一样。
案例总结:

  • a: 三个指针指向了同一个对象,这个对象是<GFPerson: 0x600000fbc1f0>;
  • b: 三个指针的地址是连续的存储在栈区中,并且从高位向低位开辟内存空间;

alloc 底层原理

  • c: 指针占用空间是8个字节;
  • d: lg1通过alloc方法开辟了内存空间,创建了对象;通过init方法初始化lg2lg3并没有开辟内存空间,也就是没有创建对象。

那么,alloc是如何开辟内存空间创建对象的呢?init又起到什么作用呢?

  • 2.2.底层探究方法

在我们的开发工程中,Jump to Definition只能看到alloc方法的声明,不能看到真正的源码实现流程。

+ (instancetype)alloc OBJC_SWIFT_UNAVAILABLE("use object initializers instead");

下面提供三种底层探究的方法。

  • 2.2.1. 添加符号断点的形式直接跟流程

我们要研究alloc方法,那就添加个符号断点alloc。符号断点添加方式见下图:

alloc 底层原理

因为我们暂时只研究GFPerson类的初始化流程,所以避免其他类调用alloc导致的干扰,运行时先将alloc断点设置为Disable Breakpoint。在程序运行到GFPerson * gf1 = [GFPerson alloc];时,再将alloc断点设置为Enable Breakpoint。运行结果见下图:

alloc 底层原理

根据上图的内容发现,[GFPerson alloc]最终走到了+[NSObject alloc];为什么是NSObject呢?因为LGPerson继承自NSObject,子类中没有alloc方法,最终会调用父类的alloc方法

并且我们还发现了一个重要线索,[NSObject alloc]来自于libobjc.A.dylib动态库。

  • 2.2.2. 通过按住 control - step into

在GFPerson * gf1 = [GFPerson alloc];这行代码添加断点,运行程序,运行到断点后,点击control – step into。操作流程见下图:

alloc 底层原理

进入后发现调用了objc_alloc,接着采用方式1添加符号断点objc_alloc,运行程序。

alloc 底层原理

同样我们也发现了一个重要线索,objc_alloc也来自于libobjc.A.dylib动态库。

  • 2.2.3. 汇编查看跟流程

设置方式:Debug -> Debug Workflow -> Always Show Disassembly。

alloc 底层原理

GFPerson * gf1 = [GFPerson alloc];这行代码添加断点,运行程序。进入汇编流程,见下图:

alloc 底层原理

看不懂汇编,但是根据关键字眼也是可以发现一些端倪的,比如同样会走到objc_alloc方法,继续采用符号断点方式查找出处。

alloc 底层原理

  • 2.2.4.探索总结

alloc 底层原理

根据上面的探索方式我们找到了alloc方法的出处,也就是动态库:libobjc.A.dylib
同时也有个疑问,初始化调用了alloc方法,但在上面的汇编跟踪发现会调用objc_alloc方法,这两个方法又有什么关系呢?
如果要深入学习alloc的实现流程,下载源码objc4源码。源码下载地址:objc4源码下载地址

三.结合源码分析alloc

源码下载完成,采用关键字alloc 全局搜索,在 NSObject.mm文件(Objective-C++汇编)中找到alloc的方法实现。

  • 1.alloc的流程分析

根据上面搜索的alloc方法实现,跟踪关键源码如下:

// alloc + (id)alloc {     return _objc_rootAlloc(self); }  // _objc_rootAlloc id _objc_rootAlloc(Class cls) {     return callAlloc(cls, false/*checkNil*/, true/*allocWithZone*/); }  // callAlloc static ALWAYS_INLINE id callAlloc(Class cls, bool checkNil, bool allocWithZone=false) { #if __OBJC2__     if (slowpath(checkNil && !cls)) return nil;     if (fastpath(!cls->ISA()->hasCustomAWZ())) {         return _objc_rootAllocWithZone(cls, nil);     } #endif      // No shortcuts available.     if (allocWithZone) {         return ((id(*)(id, SEL, struct _NSZone *))objc_msgSend)(cls, @selector(allocWithZone:), nil);     }     return ((id(*)(id, SEL))objc_msgSend)(cls, @selector(alloc)); }  // _objc_rootAllocWithZone id _objc_rootAllocWithZone(Class cls, malloc_zone_t *zone __unused) {     // allocWithZone under __OBJC2__ ignores the zone parameter     return _class_createInstanceFromZone(cls, 0, nil,                                          OBJECT_CONSTRUCT_CALL_BADALLOC); }

从源码可以得到如下流程:

alloc 底层原理

如何验证callAlloc走的是_objc_rootAllocWithZone还是objc_msgSend呢?没错上面已经学习了探索方式,这里可以使用汇编+添加符合断点!

下面设置符号断点,在程序运行到GFPerson * gf1 = [GFPerson alloc];之后再将符号断点设置为Enable Breakpoint,确保跟踪的是GFPerson的初始化流程。断点调试,发现走的是_objc_rootAllocWithZone的流程。

alloc 底层原理

在 iOS 开发中,创建对象的时候,经常会用到一个函数alloc,所以今天就探索下 alloc 的底层原理,俗话说工欲善其事必先利其器,下面我们介绍下,探索底层的东西,需要的一些基本准备东西。

准备工作

  • 1: objc是探索底层原理的一个重要工具,我们可以通过苹果开源的东西,去了解他的设计理念以及程序运行的流程,目前最新的是objc4-824,我的设备上运行起来的是objc4-818.2

  • 2: 肯定是对 iOS 开发有所了解了,起码得有 iOS 实际开发经验最少也得半年或者一年以上吧。

  • 3: 手头有一台 Mac 电脑,Mac 电脑上安装 Xcode。

  • 4: 具体objc源码配置问题可以找到 我的Github地址中查看缺少文件以及报错问题。

一.学习线索

我们平时的开发中都会认为main函数是应用程序的入口,是否是这样的?我们在 main函数 的入口添加一个断点。bt查看运行的堆栈信息,发现一些端倪!

alloc 底层原理

发现在main函数之前还有一个start,并且这个start来自动态库libdyld.dylid。说明 main函数 并不是应用程序的入口,在此之前还有一些应用程序启动过程。
很陌生,我们先从简单的开始,在这里添加一个符号断点alloc,过掉main函数入口的断点,bt查看堆栈信息,可以发现更多程序加载内容。

alloc 底层原理

比如UIKitCoreCoreFoundationlibdispach.dylib等等,我们开发过程中最常用的比如UI、NSObject、GCD等内容,均是来自这些库。

先从最熟悉的创建对象开始!!!

二.alloc原理初探

开发过程中创建对象是我们最常写的代码。
GFPerson * gf = [[GFPerson alloc] init];
留下一个问题,这里alloc做了什么,init又做了什么呢?

  • 2.1.探索案例

引入一个案例,使用 alloc方法 初始化一个对象gf1,通过gf1调用 init方法创建了 gf2gf3,然后分别输出对象、对象地址、指针地址。

alloc 底层原理

根据运行结果,发现三者的对象输出是一样的,对象地址也是一样的,指针地址不一样。
案例总结:

  • a: 三个指针指向了同一个对象,这个对象是<GFPerson: 0x600000fbc1f0>;
  • b: 三个指针的地址是连续的存储在栈区中,并且从高位向低位开辟内存空间;

alloc 底层原理

  • c: 指针占用空间是8个字节;
  • d: lg1通过alloc方法开辟了内存空间,创建了对象;通过init方法初始化lg2lg3并没有开辟内存空间,也就是没有创建对象。

那么,alloc是如何开辟内存空间创建对象的呢?init又起到什么作用呢?

  • 2.2.底层探究方法

在我们的开发工程中,Jump to Definition只能看到alloc方法的声明,不能看到真正的源码实现流程。

+ (instancetype)alloc OBJC_SWIFT_UNAVAILABLE("use object initializers instead");

下面提供三种底层探究的方法。

  • 2.2.1. 添加符号断点的形式直接跟流程

我们要研究alloc方法,那就添加个符号断点alloc。符号断点添加方式见下图:

alloc 底层原理

因为我们暂时只研究GFPerson类的初始化流程,所以避免其他类调用alloc导致的干扰,运行时先将alloc断点设置为Disable Breakpoint。在程序运行到GFPerson * gf1 = [GFPerson alloc];时,再将alloc断点设置为Enable Breakpoint。运行结果见下图:

alloc 底层原理

根据上图的内容发现,[GFPerson alloc]最终走到了+[NSObject alloc];为什么是NSObject呢?因为LGPerson继承自NSObject,子类中没有alloc方法,最终会调用父类的alloc方法

并且我们还发现了一个重要线索,[NSObject alloc]来自于libobjc.A.dylib动态库。

  • 2.2.2. 通过按住 control - step into

在GFPerson * gf1 = [GFPerson alloc];这行代码添加断点,运行程序,运行到断点后,点击control – step into。操作流程见下图:

alloc 底层原理

进入后发现调用了objc_alloc,接着采用方式1添加符号断点objc_alloc,运行程序。

alloc 底层原理

同样我们也发现了一个重要线索,objc_alloc也来自于libobjc.A.dylib动态库。

  • 2.2.3. 汇编查看跟流程

设置方式:Debug -> Debug Workflow -> Always Show Disassembly。

alloc 底层原理

GFPerson * gf1 = [GFPerson alloc];这行代码添加断点,运行程序。进入汇编流程,见下图:

alloc 底层原理

看不懂汇编,但是根据关键字眼也是可以发现一些端倪的,比如同样会走到objc_alloc方法,继续采用符号断点方式查找出处。

alloc 底层原理

  • 2.2.4.探索总结

alloc 底层原理

根据上面的探索方式我们找到了alloc方法的出处,也就是动态库:libobjc.A.dylib
同时也有个疑问,初始化调用了alloc方法,但在上面的汇编跟踪发现会调用objc_alloc方法,这两个方法又有什么关系呢?
如果要深入学习alloc的实现流程,下载源码objc4源码。源码下载地址:objc4源码下载地址

三.结合源码分析alloc

源码下载完成,采用关键字alloc 全局搜索,在 NSObject.mm文件(Objective-C++汇编)中找到alloc的方法实现。

  • 1.alloc的流程分析

根据上面搜索的alloc方法实现,跟踪关键源码如下:

// alloc + (id)alloc {     return _objc_rootAlloc(self); }  // _objc_rootAlloc id _objc_rootAlloc(Class cls) {     return callAlloc(cls, false/*checkNil*/, true/*allocWithZone*/); }  // callAlloc static ALWAYS_INLINE id callAlloc(Class cls, bool checkNil, bool allocWithZone=false) { #if __OBJC2__     if (slowpath(checkNil && !cls)) return nil;     if (fastpath(!cls->ISA()->hasCustomAWZ())) {         return _objc_rootAllocWithZone(cls, nil);     } #endif      // No shortcuts available.     if (allocWithZone) {         return ((id(*)(id, SEL, struct _NSZone *))objc_msgSend)(cls, @selector(allocWithZone:), nil);     }     return ((id(*)(id, SEL))objc_msgSend)(cls, @selector(alloc)); }  // _objc_rootAllocWithZone id _objc_rootAllocWithZone(Class cls, malloc_zone_t *zone __unused) {     // allocWithZone under __OBJC2__ ignores the zone parameter     return _class_createInstanceFromZone(cls, 0, nil,                                          OBJECT_CONSTRUCT_CALL_BADALLOC); }

从源码可以得到如下流程:

alloc 底层原理

如何验证callAlloc走的是_objc_rootAllocWithZone还是objc_msgSend呢?没错上面已经学习了探索方式,这里可以使用汇编+添加符合断点!

下面设置符号断点,在程序运行到GFPerson * gf1 = [GFPerson alloc];之后再将符号断点设置为Enable Breakpoint,确保跟踪的是GFPerson的初始化流程。断点调试,发现走的是_objc_rootAllocWithZone的流程。

alloc 底层原理

部分转自互联网,侵权删除联系

赞(0) 打赏
部分文章转自网络,侵权联系删除b2bchain区块链学习技术社区 » alloc 底层原理求职学习资料
分享到: 更多 (0)

评论 抢沙发

  • 昵称 (必填)
  • 邮箱 (必填)
  • 网址

b2b链

联系我们联系我们