??上篇文章簡單的了解了一下iOS結(jié)構(gòu)體的內(nèi)存分配,而OC對象的本質(zhì)就是結(jié)構(gòu)體。由此我們可以探究一下OC對象的內(nèi)存布局方式。
在探究過程中使用到的一些命令行
- x p ????此命令用于打印對象的內(nèi)存地址分配情況,但打印出來的內(nèi)容很難閱讀,所以可以使用下個命令進行優(yōu)化
- x/ngx p 以16進制打印對象p內(nèi)存地址,打印n段
- sizeof(p) 獲取p對象的內(nèi)存大小
- class_getInstanceSize([P class]) 獲取類對象分配的大小,需要引入運行時庫
- malloc_size((__bridge const void *)(p)) 獲取p對象在系統(tǒng)成面上分配的內(nèi)存的大小
探究對象內(nèi)存分配
以下是內(nèi)存打印狀況創(chuàng)建一個類Person,屬性定義如下:
@property(nonatomic, copy)NSString *name;
@property(nonatomic, copy)NSString *age;
@property(nonatomic, assign)int hight;
@property(nonatomic, assign)int sex;
@property(nonatomic, assign)double x;

截屏2020-10-28 17.22.27.png
對象內(nèi)部的內(nèi)存地址分配方式打印分析:
- person是一個指針類型,在OC中指針的大小為8字節(jié),所以sizeof(person)輸出為8字節(jié)
- Person是一個類,本質(zhì)是個結(jié)構(gòu)體,經(jīng)過分析可得出內(nèi)存占用是32字節(jié)。但實際打印是40,原因是OC對象本身有一個isa指針,該指針占用了8字節(jié)。ps:這也是為什么我們打印數(shù)組的首地址不是第一個元素地址的原因
- Person類本身的內(nèi)存占用是按照最大8字節(jié)對齊,所以為40位。但蘋果當前的內(nèi)存分配是16位對齊,所以其在內(nèi)存開辟時實際開辟的大小由于對齊方式的原因最終開辟出的大小為48位

截屏2020-10-28 17.24.26.png
在隨意一處打印斷點,在命令行使用x p命令可以獲取對象內(nèi)存分配方式,這種方式獲取的內(nèi)存分配很難讀懂,所以可以作為了解

截屏2020-10-28 17.35.38.png
使用x/nxg p 命令可以按照每段8位的16進制形式打印內(nèi)存。由于Person類本身占用內(nèi)存為48字節(jié),所以使用x/6xg 打印出所有內(nèi)存的分配方式
數(shù)據(jù)意義分析
- 每行的第一個地址如0x600003b80600代表著該段內(nèi)存空間在內(nèi)存中的地址,由于系統(tǒng)按照16位對齊,所以看到三段內(nèi)存地址是順序遞增的
- 由于OC對象默認有一個isa的指針,所以打印第一個地址為Peron對象本身
- 按照結(jié)構(gòu)體內(nèi)存分配原則理論上我們打印0x00000001000000b9位置的內(nèi)存該輸出屬性的name,但實際會打印出一串數(shù)字。原因在于屬性中有兩個int類型,內(nèi)存大小為4字節(jié),為了保證可讀性蘋果對齊進行了優(yōu)化,所以這兩個屬性是以16進制存放在0x00000001000000b9這個內(nèi)存地址。另外對于數(shù)值類型蘋果也會對其進行優(yōu)化,所以可以通過內(nèi)存空間地址直接獲取對應的值
- 可以看到最后一個內(nèi)存地址為0x000000000000000,對其進行打印發(fā)現(xiàn)最終輸出為nill。這也說明了Person類本身占用的地址空間為40字節(jié),但系統(tǒng)實際開辟的內(nèi)存空間為48位,遵循16進制對齊的原則
??????以上就是此次對于OC對象內(nèi)存空間分配的探究過程,如有錯誤歡迎評價指正哦~