我們在調用block時,如果這個block為nil,則程序會崩潰,報類似於EXC_BAD_ACCESS(code=1, address=0xc)異常【32位下的結果,如果是64位,則address=0x10】。如圖1,這個異常表示程序在試圖讀取內存地址0xc的信息時出錯。
在定義一個block時,編譯器會在棧上創建一個結構體,類似於圖2的結構體。
block就是指向這個結構體的指針。其中的invoke就是指向具體實現的函數指針。當block被調用時,程序最終會跳轉到這個函數指針指向的代碼區。而當block為nil時,程序就會試圖去讀取0xc地址的信息,而這個地址什么都不會有(duff address),於是拋出一個segmentation fault。在32位系統下,之所以是0xc,是因為invoke前面的三個成員變量的大小正好是12。
所以我們在使用block時,應該首先去判斷block是否為空。一種比較優雅的寫法是:
!block ?: block()