Objc中向一個nil物件傳送訊息會怎樣
我們知道在 Objective-C 中給 nil 傳送訊息程式不會崩潰,
Objective-C 是以 C 語言為基礎的,
PC 上,在 C 語言中對空指標進行操作,
程式會由於越界訪問而出現保護錯進而崩潰,
但是 Objective-C 中為什麼不會崩潰呢?
原因需要從原始碼中尋找,
下面是 objc_msgSend 的 arm 版彙編程式碼片段:
在 arm 的函式呼叫過程中,
一般用 r0-r4 傳遞引數,
用 r0 傳遞返回值。
對應 objc_msgSend,第一個引數為 self,返回值也是 self,都放在 r0(a1)中。
/********************************************************************
* idobjc_msgSend(idself, SELop, ...)
* On entry: a1 is the message receiver,
* a2 is the selector
********************************************************************/
ENTRY objc_msgSend
# check whether receiver is nil
teq a1, #0
moveq a2, #0
bxeq lr
teq 指令說明:
TEQ
R
n
, Operand2
The TEQ instruction performs a bitwise Exclusive OR operation on the value in Rn and the value of Operand2.
測試 self 是否為空。
moveq 指令說明:
如果self為空,則將 selector 也設定為空。
bx 指令說明:
在 arm 中 bx lr 用來返回到呼叫子程式的地方(即:返回到呼叫者),此處是:如果 self 為空,就返回到呼叫 objc_msgSend 的地方繼續執行。
總之:
如果傳遞給 objc_msgSend 的 self 引數是 nil,該函式不會執行有意義的操作,直接返回。
因為OC的函式都是通過objc_msgSend
進行訊息傳送來實現的,相對於C和C++來說,對於空指標的操作會引起crash問題,而objc_msgSend
會通過判斷self來決定是否傳送訊息,如果self為nil,那麼selector
也會為空,直接返回,不會出現問題。視方法返回值,向nil發訊息可能會返回nil(返回值為物件),0(返回值為一些基礎資料)或 返回值為結構體,傳送給 nil 的訊息將返回0,結構體中各個欄位的值將都是0,等等。但對於[NSNull null]物件傳送訊息時,是會crash的,因為NSNull類只有一個null方法。