iOS的alloc的底層代碼流程
前言
創建類的一個物件的時候,alloc的底層做了什么呢?今天就好好的研究一下,
測驗代碼:
LGPerson *p1 = [LGPerson alloc];
LGPerson *p2 = [p1 init];
LGPerson *p3 = [p1 init];
NSLog(@"%@-%p-%p",p1,p1,&p1);
NSLog(@"%@-%p-%p",p2,p2,&p2);
NSLog(@"%@-%p-%p",p3,p3,&p3);
列印結果是:
<LGPerson: 0x600001218290>-0x600001218290-0x16ced7f48
<LGPerson: 0x600001218290>-0x600001218290-0x16ced7f40
<LGPerson: 0x600001218290>-0x600001218290-0x16ced7f38
alloc出來之后就有了一片記憶體空間,p1,p2,p3都有了一個指標地址,這3個指標地址同時指向這個記憶體空間,這3個所指的地址在堆疊里面,如:&p1,指向這個記憶體空間為堆,這3個物件為連續開辟,在堆疊里面是連續的指標,
三種方式查看底層代碼及流程
在p1處,加個斷點,重新運行,就會進入 -[ViewController viewDidLoad]:
看底層原始碼,及怎么走的:
一、結合符號斷點
得到:libobjc.A.dylib`objc_alloc:
然后按 ctrl+setup into(xcode的列印區上面的向下的箭頭), 進入objc_alloc,可以看到:


可以看到進入到了objc_alloc的一個函式,要看到底層的原始碼,怎么走的,需要加一個System Breakpoint斷點,objc_alloc,然后點擊 continue program execution按鈕(右箭頭),可以進入libobjc.A.dylib`objc_alloc:
的底層:

底層下一步是要到_objc_rootAllocWithZone,
二、結合匯編去看
匯編跟流程,加符號斷點objc_alloc
選擇上面的Debug-> Debug Workflow-> Always Show Disassembly是設定匯編顯示:

可以看到下一步是到 symbol stub for:objc_alloc,在這里加個斷點,點擊continue program execution按鈕,就到這一行了,再點擊ctrl+setup into按鈕,就又到了objc_alloc:

三、通過符號斷點,確定未知
得到:libobjc.A.dylib`+[NSObject alloc]:
前提是:需要去蘋果官網下載objc的原始碼(搜索objc可以找到),
去掉匯編顯示的,選擇上面的Debug-> Debug Workflow-> Always Show Disassembly,反選,
加一個System Breakpoint斷點,olloc,然后點擊continue program execution按鈕,到:libobjc.A.dylib`+[NSObject alloc]:

看原始碼:



可知:alloc -> _objc_rootAlloc -> callAlloc
從callAlloc 中可以看到 _objc_rootAllocWithZone和objc_msgSend兩個方法,但是是那個先跑呢?
需要在p1處加個斷點,運行,可以見到運行到alloc的地方,加System Breakpoint斷點,分別是:_objc_rootAlloc ,callAlloc,_objc_rootAllocWithZone這三個斷點,
然后點擊continue program execution按鈕,到:

可以看到是先跑:_objc_rootAlloc,再跑:_objc_rootAllocWithZone,再跑:objc_msgSend的,
通過原始碼可以看到:


跑了:_objc_rootAllocWithZone,再跑:_class_createInstanceFromZone,在原始碼中運行,打斷點運行到這里:LGPerson *p = [LGPerson alloc];
然后在==_class_createInstanceFromZone==
方法里面打斷點:

可以看出size這里的cls->instanceSize是先計算出需要的記憶體空間大小,向下面走,到這里:

可以看到obj已經有了地址,但是obj卻又沒有使用過,可知是分配的是臟記憶體地址,沒有被開辟出來,
接著往下走:

可以看到走到了calloc這里:
接著走:

可以看到obj的地址變了,有了一個新的地址,說明在calloc里面對obj進行了新的地址賦值,我們已知obj是一個物件,是一個類的物件,類的物件是isa,從地址上可知,當前地址還沒有和類關聯起來,
繼續走:

走到了obj->initInstanceIsa這里,
繼續走:

列印obj的地址,發現關聯上了LGPerson的類,
然后就是物件回傳類出去:

總結:
alloc的流程是:
alloc -> _objc_rootAlloc -> callAlloc -> _objc_rootAllocWithZone -> objc_msgSend,
其中跑完_objc_rootAllocWithZone -> _class_createInstanceFromZone, 之后是先cls->instanceSize,再是calloc里面給物件賦值新的記憶體地址,最后是obj->initInstanceIsa讓物件的地址關聯上了類,
alloc的流程研究已經完成,可知就是開辟一個記憶體并與類關聯起來,
轉載請註明出處,本文鏈接:https://www.uj5u.com/yidong/286416.html
標籤:其他
