關(guān)于alloc的底層分析

用到的軟硬件
1、Macbook Air
2、macOS Mojave 10.14.6
3、Xcode 11.3.1
4、Object-C(編程語言)

那么首先第一步我們先打開我們的macbook電腦,然后運(yùn)行我們的xcode,創(chuàng)建我們的第一個(gè)工程,這里我就取名為alloc_init_test(如圖)


1.png

2.png

3.png

廢話說了好多進(jìn)入正題吧,首先找到我們的main.m文件在里面添加代碼,然后在確定我們的研究對(duì)象,以NSObject的alloc來研究,所以創(chuàng)建一個(gè)類來繼承NSObject,這里我以創(chuàng)建Person的NSObject為例(至于為什么用NSObject 而不是 其他什么NSArray ,ViewCongroller為例,我只能抱歉,因?yàn)榘l(fā)現(xiàn)很多問題)

#import <UIKit/UIKit.h>
#import "AppDelegate.h"
#import "Person.h"

int main(int argc, char * argv[]) {
    NSString * appDelegateClassName;
    @autoreleasepool {
        // Setup code that might create autoreleased objects goes here.
        appDelegateClassName = NSStringFromClass([AppDelegate class]);

        Person *p = [[Person alloc] init];
        NSLog(@"%@",p);
    }
    return UIApplicationMain(argc, argv, nil, appDelegateClassName);
}

按住我們的cmmad鍵,點(diǎn)擊alloc再點(diǎn)擊Jump to Definition,這時(shí)候會(huì)發(fā)現(xiàn),這里雖然跳轉(zhuǎn)到了,但是根本沒辦法讀取到alloc這個(gè)函數(shù)是如何實(shí)現(xiàn)的。這個(gè)是因?yàn)樘O果封裝了alloc的實(shí)現(xiàn)函數(shù),在一個(gè)包體里面。你只能看到alloc的在.h文件里面的定義。那么怎么辦呢?。?!
其實(shí)蘋果在很久以前就開源了一部分的核心代碼,那么我可以告訴大家我們這里的alloc的方法定義在objc4,那么大家問,為什么你會(huì)知道alloc的方法在objc4這個(gè)源碼文件里面。很遺憾,我只能說,過程我也沒有弄明白,所以我也不敢寫出來。

首先
1、蘋果開源源碼地址:opensource.apple.com/tarballs/
2、給出別人已經(jīng)編譯好的iOS_objc4-756.2 最新源碼編譯調(diào)試,可以直接使用。

好這里我弄到了一份objc4-750的原生代碼,并且配置好了可以直接運(yùn)行我們的Person進(jìn)行調(diào)試。也就是說在我們的原生代碼里面,跑我們自己寫的東西,可以看到原生里面實(shí)現(xiàn)的方法and過程。好像有點(diǎn)帥。。

在我們配置好的objc4-750代碼里(ps:這里需要配置一個(gè)Target,不然進(jìn)入不鳥斷點(diǎn)哦,配置方式
我這里配置了一個(gè)Alloctest的Target,配置完成后會(huì)生成一個(gè)Alloctest的文件夾,里面有一個(gè)main.m的文件,好了,你懂得,加入我們的Person類文件,并且在main.m里面添加代碼

#import <Foundation/Foundation.h>
#import "Person.h"

int main(int argc, const char * argv[]) {
    @autoreleasepool {
        // insert code here...
        NSLog(@"Hello, World!");
        Person *p = [[Person alloc] init];
        NSLog(@"%@",p);
    }
    return 0;
}

然后在Person這里打入我們的斷點(diǎn)。運(yùn)行即可調(diào)試。

好,讓我們一步一步的來追蹤,
斷點(diǎn)_push_01

+ (id)alloc {
    //好像沒有什么太多解釋的東西
    return _objc_rootAlloc(self);
}

斷點(diǎn)_push_02

_objc_rootAlloc(Class cls)
{
    return callAlloc(cls, false/*checkNil*/, true/*allocWithZone*/);
}

斷點(diǎn)_push_03

callAlloc(Class cls, bool checkNil, bool allocWithZone=false)
{
    if (slowpath(checkNil && !cls)) return nil;
//用于判斷objective-c 版本,是不是2.0,目前我們使用的objective-c版本都是此版本。
#if __OBJC2__
    //如果該對(duì)象沒有自己的allocWithZone方法需要實(shí)現(xiàn),這里我不懂
    if (fastpath(!cls->ISA()->hasCustomAWZ())) {
        // No alloc/allocWithZone implementation. Go straight to the allocator.
        // fixme store hasCustomAWZ in the non-meta class and 
        // add it to canAllocFast's summary
        //查看一下類是否能快速分配內(nèi)存
        if (fastpath(cls->canAllocFast())) {
            // No ctors, raw isa, etc. Go straight to the metal.
            //查看一下類是否有析構(gòu)函數(shù)
            bool dtor = cls->hasCxxDtor();
           //分配內(nèi)存,給obj對(duì)象
            id obj = (id)calloc(1, cls->bits.fastInstanceSize());
            //如果分配失敗,那么交給錯(cuò)誤處理
            if (slowpath(!obj)) return callBadAllocHandler(cls);
            //初始化obj的isa
            obj->initInstanceIsa(cls, dtor);
            return obj;
        }
        else {
            // Has ctor or raw isa or something. Use the slower path.
            id obj = class_createInstance(cls, 0);
            if (slowpath(!obj)) return callBadAllocHandler(cls);
            return obj;
        }
    }
#endif

    // No shortcuts available.
    //如果allocWithZone 為true,則實(shí)現(xiàn)allocWithZone 方法
    if (allocWithZone) return [cls allocWithZone:nil];
    return [cls alloc];
}

這里有一個(gè)問題,就是關(guān)于這句話slowpath(checkNil && !cls),找了一堆的資料也不知所以然。跳進(jìn)這個(gè)方法里面是一個(gè)宏定義

#define fastpath(x) (__builtin_expect(bool(x), 1))
#define slowpath(x) (__builtin_expect(bool(x), 0))

__builtin_expect這個(gè)指令是gcc引入的,作用是允許程序員將最有可能執(zhí)行的分支告訴編譯器。這個(gè)指令的寫法為:__builtin_expect(EXP, N)。
意思是:EXP==N的概率很大。
好吧,這里我的理解只能是,提高編譯效率。。。
這里參考了兩篇文章
iOS——runtime(4):淺析對(duì)象的創(chuàng)建
iOS——runtime(5):allocWithZone剖析

好了 最后最后附上一張alloc的流程圖。。。。

alloc流程圖.png
最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請(qǐng)聯(lián)系作者
【社區(qū)內(nèi)容提示】社區(qū)部分內(nèi)容疑似由AI輔助生成,瀏覽時(shí)請(qǐng)結(jié)合常識(shí)與多方信息審慎甄別。
平臺(tái)聲明:文章內(nèi)容(如有圖片或視頻亦包括在內(nèi))由作者上傳并發(fā)布,文章內(nèi)容僅代表作者本人觀點(diǎn),簡書系信息發(fā)布平臺(tái),僅提供信息存儲(chǔ)服務(wù)。

友情鏈接更多精彩內(nèi)容