OC物件為什麼需要16位元組

2021-10-14 18:25:28 字數 1408 閱讀 7422

問題:  使用sizeof(obj)列印物件所佔空間時, 輸出的是8, 使用class_getinstancesize(obj.class)輸出的卻是16 ? (此處的obj 是 nsobject 的例項)

從蘋果官方開源的objc4原始碼中來尋找答案, 根據alloc流程一步一步追蹤

alloc -> _objc_rootalloc -> callalloc -> _objc_rootallocwithzone -> _class_createinstancefromzone -> instancesize

追蹤到 instancesize (size_t extrabytes) 這個方法, 入參extrabytes為0,

再次進入fastpath的條件判斷中, cache.fastinstancesize(extrabytes),

進入 fastinstancesize 的方法, 看到 

size_t size = _flags & fast_cache_alloc_mask;  // _flags 是 nopointisa的標識位 size = 16

return align16(size + extra - fast_cache_alloc_delta16); // align16(16 + 0 - 0x0008 = 8)

align16 的入參是8, 從其字面上來看 是 16位元組對齊的意思, 我們繼續進入來看一看,

static inline size_t align16(size_t x)
看到這個方法, 仔細解讀了一下, 這是 向上取16倍數的一種方法, 如下:

8 + 15 = 23

15的 二進位制 0b 0000 0000 0000 1111

23的 二進位制 0b 0000 0000 0001 0111

15取反 ~15 0b 1111 1111 1111 0000

進行與運算 &

result 0b 0000 0000 0001 0000

可以得到最後結果是 16

同理, 向下取16倍數的方式是:   x & ~(15)

這就得到了物件所佔記憶體是16個位元組的證據, 但是為什麼呢? (蘋果早期的版本其實是8位元組對齊的)

任何乙個物件都有自己的 isa, 記憶體佔8位元組, 如果是8位元組對齊的話, 物件之間 isa 都是緊鄰的, 沒有一點空隙, 如果記憶體訪問出現了一點錯誤或者偏移, 就會訪問到其他物件, 就會出現一些野指標,記憶體訪問錯誤之類, 發生了混亂, 所以為了使得物件之間的訪問更加的安全, 就需要給物件之前預留一部分的空間, 預留多少合適呢, 毫無疑問, 當然是8位元組, 為什麼不是1,2,4位元組呢? 一方面16位元組是可以占用最小空間的合理記憶體空間, 即8的倍數, 另一方面也更加的安全, 各個物件的記憶體都是16位元組, 偏移和訪問時, 可以很好地進行對齊. 

為什麼 C 中成員函式指標是 16 位元組?

當我們討論指標時,通常假設它是一種可以用void 指標來表示的東西,在 x86 64 平台下是 8 個位元組大小。例如,下面是來自 維基百科中關於 x86 64 的文章 的摘錄 pushes and pops on the stack are always in 8 byte strides,and...

為什麼 C 中成員函式指標是 16 位元組?

當我們討論指標時,通常假設它是一種可以用void 指標來表示的東西,在 x86 64 平台下是 8 個位元組大小。例如,下面是來自 維基百科中關於 x86 64 的文章 的摘錄 pushes and pops on the stack are always in 8 byte strides,and...

為什麼1位元組是8位

因為計算機用二進位制,所以希望基本儲存單位的是2的n次方。2 1 2 可以表示 4 個符號 2 2 4 可以表示 16 個符號 2 3 8 可以表示 256 個符號 2 4 16 可以表示 65536個符號 考慮需要表示英文本元和數字以及一些符號的數量,大家認為用幾位來表示比較合適?早期 其實也不早...