關(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文件里面的定義锰蓬。那么怎么辦呢!C袖觥芹扭!
其實(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)系作者
  • 序言:七十年代末低剔,一起剝皮案震驚了整個(gè)濱河市速梗,隨后出現(xiàn)的幾起案子,更是在濱河造成了極大的恐慌襟齿,老刑警劉巖姻锁,帶你破解...
    沈念sama閱讀 217,277評(píng)論 6 503
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件,死亡現(xiàn)場(chǎng)離奇詭異猜欺,居然都是意外死亡位隶,警方通過查閱死者的電腦和手機(jī),發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 92,689評(píng)論 3 393
  • 文/潘曉璐 我一進(jìn)店門开皿,熙熙樓的掌柜王于貴愁眉苦臉地迎上來涧黄,“玉大人,你說我怎么就攤上這事赋荆∷裢祝” “怎么了?”我有些...
    開封第一講書人閱讀 163,624評(píng)論 0 353
  • 文/不壞的土叔 我叫張陵窄潭,是天一觀的道長(zhǎng)春宣。 經(jīng)常有香客問我,道長(zhǎng)嫉你,這世上最難降的妖魔是什么信认? 我笑而不...
    開封第一講書人閱讀 58,356評(píng)論 1 293
  • 正文 為了忘掉前任,我火速辦了婚禮均抽,結(jié)果婚禮上嫁赏,老公的妹妹穿的比我還像新娘。我一直安慰自己油挥,他們只是感情好潦蝇,可當(dāng)我...
    茶點(diǎn)故事閱讀 67,402評(píng)論 6 392
  • 文/花漫 我一把揭開白布款熬。 她就那樣靜靜地躺著,像睡著了一般攘乒。 火紅的嫁衣襯著肌膚如雪贤牛。 梳的紋絲不亂的頭發(fā)上,一...
    開封第一講書人閱讀 51,292評(píng)論 1 301
  • 那天则酝,我揣著相機(jī)與錄音殉簸,去河邊找鬼。 笑死沽讹,一個(gè)胖子當(dāng)著我的面吹牛般卑,可吹牛的內(nèi)容都是我干的。 我是一名探鬼主播爽雄,決...
    沈念sama閱讀 40,135評(píng)論 3 418
  • 文/蒼蘭香墨 我猛地睜開眼蝠检,長(zhǎng)吁一口氣:“原來是場(chǎng)噩夢(mèng)啊……” “哼!你這毒婦竟也來了挚瘟?” 一聲冷哼從身側(cè)響起叹谁,我...
    開封第一講書人閱讀 38,992評(píng)論 0 275
  • 序言:老撾萬榮一對(duì)情侶失蹤,失蹤者是張志新(化名)和其女友劉穎乘盖,沒想到半個(gè)月后焰檩,有當(dāng)?shù)厝嗽跇淞掷锇l(fā)現(xiàn)了一具尸體,經(jīng)...
    沈念sama閱讀 45,429評(píng)論 1 314
  • 正文 獨(dú)居荒郊野嶺守林人離奇死亡订框,尸身上長(zhǎng)有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點(diǎn)故事閱讀 37,636評(píng)論 3 334
  • 正文 我和宋清朗相戀三年析苫,在試婚紗的時(shí)候發(fā)現(xiàn)自己被綠了。 大學(xué)時(shí)的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片布蔗。...
    茶點(diǎn)故事閱讀 39,785評(píng)論 1 348
  • 序言:一個(gè)原本活蹦亂跳的男人離奇死亡藤违,死狀恐怖浪腐,靈堂內(nèi)的尸體忽然破棺而出纵揍,到底是詐尸還是另有隱情,我是刑警寧澤议街,帶...
    沈念sama閱讀 35,492評(píng)論 5 345
  • 正文 年R本政府宣布泽谨,位于F島的核電站,受9級(jí)特大地震影響特漩,放射性物質(zhì)發(fā)生泄漏吧雹。R本人自食惡果不足惜,卻給世界環(huán)境...
    茶點(diǎn)故事閱讀 41,092評(píng)論 3 328
  • 文/蒙蒙 一涂身、第九天 我趴在偏房一處隱蔽的房頂上張望雄卷。 院中可真熱鬧,春花似錦蛤售、人聲如沸丁鹉。這莊子的主人今日做“春日...
    開封第一講書人閱讀 31,723評(píng)論 0 22
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽揣钦。三九已至雳灾,卻和暖如春,著一層夾襖步出監(jiān)牢的瞬間冯凹,已是汗流浹背谎亩。 一陣腳步聲響...
    開封第一講書人閱讀 32,858評(píng)論 1 269
  • 我被黑心中介騙來泰國(guó)打工, 沒想到剛下飛機(jī)就差點(diǎn)兒被人妖公主榨干…… 1. 我叫王不留宇姚,地道東北人匈庭。 一個(gè)月前我還...
    沈念sama閱讀 47,891評(píng)論 2 370
  • 正文 我出身青樓,卻偏偏與公主長(zhǎng)得像空凸,于是被迫代替她去往敵國(guó)和親嚎花。 傳聞我的和親對(duì)象是個(gè)殘疾皇子,可洞房花燭夜當(dāng)晚...
    茶點(diǎn)故事閱讀 44,713評(píng)論 2 354