Tagged Pointer

NSNumber

因為在從32位升級到64位后,同一個對象占用的內存會變成原來的2倍,為了節省內存和訪問效率而引入了TaggedPointer. 像NSNumber,NSDate的地址不是真正的地址,如果是NSNumber@(1),@(2),那么地址分別是是

(__NSCFNumber *) $0 = 0xb000000000000012 (int)1
(__NSCFNumber *) $3 = 0xb000000000000022 (int)2

我們發現倒數第2位就是存儲的真實值,它會以0xb......2這樣的格式展示,指針包含兩部分,一部分是真實值,一部分是特殊標記。但是這樣的話,如果數值過大,位數就不夠了。我們測試一下,我們用一個特別大的值,@(0xEFFFFFFFFFFFFFFF),地址是:

(__NSCFNumber *) $5 = 0x00006000000320e0 

結果很像一個指針,這個是真正的指針,它沒有用到TaggedPointer。

ISA失效

雖然taggedPointer有一定的好處,但是它并不是一真正的對象,而是個偽對象,所以我們不能直接獲取它的isa,否則就會報錯。為了獲取Isa,我們定義一個假的tempObject結構體來抽取isa指針:

    struct tempObject {
        Class isa;
    };
    ViewController *vc = [[ViewController alloc] init];
    struct tempObject *oo = (__bridge struct tempObject *)number;
    Class isa = oo->isa;

結果運行時報錯,訪問了野指針:

Thread 1: EXC_BAD_ACCESS (code=EXC_I386_GPFLT)

說明它根本就沒有isa指針。但是如果我們用object_getClass()[NSNumber Class]來獲取isa時會返正確的的Class:__NSCFNumber。因為蘋果已經偽裝好了,很多runtime API里都會判斷是否是TaggedPointer對象,會對它單獨進行處理。

最后編輯于
?著作權歸作者所有,轉載或內容合作請聯系作者
平臺聲明:文章內容(如有圖片或視頻亦包括在內)由作者上傳并發布,文章內容僅代表作者本人觀點,簡書系信息發布平臺,僅提供信息存儲服務。

推薦閱讀更多精彩內容