OC 內存對其原理分析

上一篇文章我們講到 alloc 在開辟內存空間之前,對對要分配的內存空間提前進行計算,并最終使用 16 字節對其方法進行對其,提升了讀取的效率。但是16 字節對其之前,如何計算對象實際需要的空間呢?

1. 對象內存分析

先展示一段測試代碼

@interface LGPerson : NSObject

@property (nonatomic, strong) NSString *name;
@property (nonatomic, strong) NSString *name1;
@property (nonatomic, assign) short a;
@property (nonatomic, assign) int b;
@property (nonatomic, assign) double c;

@end

// 調用  
LGPerson *person = [[LGPerson alloc] init];

NSLog(@"sizeof——%lu", sizeof([person class]));
NSLog(@"class_getInstanceSize——%lu", class_getInstanceSize([person class]));
NSLog(@"malloc_size——%lu", malloc_size((__bridge const void *)(person)));

sizeof——8
class_getInstanceSize——40
malloc_size——48

這里可以發現,對于類本身,sizeof 可以查詢到它所占用的地址空間只有 8 位。

而 class_getInstanceSize 為何是 40?沒有 16 進制對其?

其實 class_getInstanceSize 獲取到的是實例對象實際需要占用的內存空間,而且實際使用一般只會做 8 字節對齊。

而 malloc_size 則是系統實際為該實例對象分配的空間。也就是經過 16 字節對其后的效果。

2. 結構體內存對齊

看完了對象,我們看下結構體是如何進行內存對齊的。(實際上要比對象對其要簡單些,并且不涉及 16 進制對其的優化,能更直觀的得出內存空間實際占用的計算)

預備知識

在展示實例之前,我們先看下實例中用到的類型的內存空間情況

NSLog(@"double size %lu", sizeof(double));
NSLog(@"int size%lu", sizeof(int));
NSLog(@"short size %lu", sizeof(short));
NSLog(@"char size %lu", sizeof(char));
NSLog(@"NSString size %lu", sizeof(NSString *));

// double size 8
// int size 4
// short size 2
// char size 1
// NSString * size 8(存儲地址)

初級案例

ok,這些類型的空間大小大家應該熟悉了。下面介紹實例

typedef struct Str1 {
  int o;
  short s;
  char a;
  double c;
  NSString *x;
} S1;

typedef struct Str2 {
  double a;
  int d;
  short b;
  char c;
  S1 s1;
} S2;
NSLog(@"%lu", sizeof(S1)); // 24
NSLog(@"%lu", sizeof(S2)); // 40

我們先來看下結構體 Str1 的內存大小 - 16。

實際上,基礎類型的存儲位置為棧內存,而結構體的存儲也使用了內存對其的技術,用于減少 cpu? 的訪問內存次數,提升讀取效率。

首先我們需要了解一下結構體內存對其的規則:

  1. 結構體變量的首地址是其最長基本類型成員的整數倍;
  2. 結構體每個成員相對于結構體首地址的偏移量(offset)都是成員大小的整數倍,如不滿足,對前一個成員填充字節以滿足;
  3. 結構體的總大小為結構體最大基本類型成員變量大小的整數倍;
  4. 結構體中的成員變量都是分配在連續的內存空間中。
    typedef struct Str1 {
      int o; // 占用 4 字節,分別為 0 ~ 3
      short s; // 占用 2 字節,分別為 4 ~ 5
      char a; // 占用 1 字節, 分別為 6
      NSString *x; // 占用8字節, 但由于規則2限制,需要對空間 7 進行填充,實際存儲位置為 8 ~ 15
      double c; // 占用8字節,分別為 16 - 23
    } S1; // 根據規則3,最大成員大小為8,0~23 總共占用24字節,剛好符合 8 的倍數。
    
    NSLog(@"%lu", S1); // 24

所以,根據規則,我們得出上述結構體 Str1 內存大小為 24 字節。

進階案例

上面案例中,str2 是一個嵌套類型結構體,他的大小又是如何求得的呢?

??知識點:結構體嵌套的內存對其方式

如果一個結構體B里嵌套另一個結構體A,還是以最大成員類型的字節對齊,但是結構體A存儲起點為A內部最大成員整數倍的地方。(struct B里存有struct A,A里有char,int,double等成員,那A應該從8的整數倍開始存儲。),結構體A中的成員的對齊規則仍滿足自身的規則

typedef struct Str2 {
  double a; // 8字節 0 ~ 7
  int d; // 4 字節: 8 ~ 11
  short b; // 2字節: 12 ~ 13
  char c; // 1字節: 14
  S1 s1; // 根據上面的結果,此處大小為 24 字節。此處需要注意,依據結構體嵌套對其方式,存儲起始點則為最長 8 字節的倍數,即 16 ~ 39
} S2; // 綜上,40 剛好為 8 的整數倍。即如 sizeof 得出的結果為,40
?著作權歸作者所有,轉載或內容合作請聯系作者
  • 序言:七十年代末,一起剝皮案震驚了整個濱河市,隨后出現的幾起案子,更是在濱河造成了極大的恐慌,老刑警劉巖,帶你破解...
    沈念sama閱讀 227,533評論 6 531
  • 序言:濱河連續發生了三起死亡事件,死亡現場離奇詭異,居然都是意外死亡,警方通過查閱死者的電腦和手機,發現死者居然都...
    沈念sama閱讀 98,055評論 3 414
  • 文/潘曉璐 我一進店門,熙熙樓的掌柜王于貴愁眉苦臉地迎上來,“玉大人,你說我怎么就攤上這事。” “怎么了?”我有些...
    開封第一講書人閱讀 175,365評論 0 373
  • 文/不壞的土叔 我叫張陵,是天一觀的道長。 經常有香客問我,道長,這世上最難降的妖魔是什么? 我笑而不...
    開封第一講書人閱讀 62,561評論 1 307
  • 正文 為了忘掉前任,我火速辦了婚禮,結果婚禮上,老公的妹妹穿的比我還像新娘。我一直安慰自己,他們只是感情好,可當我...
    茶點故事閱讀 71,346評論 6 404
  • 文/花漫 我一把揭開白布。 她就那樣靜靜地躺著,像睡著了一般。 火紅的嫁衣襯著肌膚如雪。 梳的紋絲不亂的頭發上,一...
    開封第一講書人閱讀 54,889評論 1 321
  • 那天,我揣著相機與錄音,去河邊找鬼。 笑死,一個胖子當著我的面吹牛,可吹牛的內容都是我干的。 我是一名探鬼主播,決...
    沈念sama閱讀 42,978評論 3 439
  • 文/蒼蘭香墨 我猛地睜開眼,長吁一口氣:“原來是場噩夢啊……” “哼!你這毒婦竟也來了?” 一聲冷哼從身側響起,我...
    開封第一講書人閱讀 42,118評論 0 286
  • 序言:老撾萬榮一對情侶失蹤,失蹤者是張志新(化名)和其女友劉穎,沒想到半個月后,有當地人在樹林里發現了一具尸體,經...
    沈念sama閱讀 48,637評論 1 333
  • 正文 獨居荒郊野嶺守林人離奇死亡,尸身上長有42處帶血的膿包…… 初始之章·張勛 以下內容為張勛視角 年9月15日...
    茶點故事閱讀 40,558評論 3 354
  • 正文 我和宋清朗相戀三年,在試婚紗的時候發現自己被綠了。 大學時的朋友給我發了我未婚夫和他白月光在一起吃飯的照片。...
    茶點故事閱讀 42,739評論 1 369
  • 序言:一個原本活蹦亂跳的男人離奇死亡,死狀恐怖,靈堂內的尸體忽然破棺而出,到底是詐尸還是另有隱情,我是刑警寧澤,帶...
    沈念sama閱讀 38,246評論 5 355
  • 正文 年R本政府宣布,位于F島的核電站,受9級特大地震影響,放射性物質發生泄漏。R本人自食惡果不足惜,卻給世界環境...
    茶點故事閱讀 43,980評論 3 346
  • 文/蒙蒙 一、第九天 我趴在偏房一處隱蔽的房頂上張望。 院中可真熱鬧,春花似錦、人聲如沸。這莊子的主人今日做“春日...
    開封第一講書人閱讀 34,362評論 0 25
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽。三九已至,卻和暖如春,著一層夾襖步出監牢的瞬間,已是汗流浹背。 一陣腳步聲響...
    開封第一講書人閱讀 35,619評論 1 280
  • 我被黑心中介騙來泰國打工, 沒想到剛下飛機就差點兒被人妖公主榨干…… 1. 我叫王不留,地道東北人。 一個月前我還...
    沈念sama閱讀 51,347評論 3 390
  • 正文 我出身青樓,卻偏偏與公主長得像,于是被迫代替她去往敵國和親。 傳聞我的和親對象是個殘疾皇子,可洞房花燭夜當晚...
    茶點故事閱讀 47,702評論 2 370