成人免费xxxxx在线视频软件_久久精品久久久_亚洲国产精品久久久_天天色天天色_亚洲人成一区_欧美一级欧美三级在线观看

聊聊iOS OC 對象的內存對齊原則

移動開發 iOS
經過各種分析,我們可以得到的結論是 instanceSize 是以 8 字節進行對齊的, 后面 calloc 是以 16 字節進行對齊的,說明 calloc 進一步對對象進行了處理。也就解釋了我們打印出來的 40-48 了。

[[409899]]

本文轉載自微信公眾號「網羅開發」,作者just東東。轉載本文請聯系網羅開發公眾號。

問題的引入

初始化一個 OC 類,具有如下屬性:

  1. #import <Foundation/Foundation.h> 
  2.  
  3. NS_ASSUME_NONNULL_BEGIN 
  4.  
  5. @interface LGTeacher : NSObject 
  6. @property (nonatomic, copy) NSString *name
  7. @property (nonatomic, assign) int age; 
  8. @property (nonatomic, assign) long height; 
  9. @property (nonatomic, strong) NSString *hobby; 
  10.  
  11. @end 
  12.  
  13. NS_ASSUME_NONNULL_END 

初始化對象,并獲取對象的內存 size:

  1. LGTeacher  *p = [[LGTeacher alloc] init]; 
  2. p.name = @"LG_Cooci"
  3. p.age  = 18; 
  4. p.height = 185; 
  5. p.hobby  = @"女"
  6.  
  7. NSLog(@"%lu - %lu",class_getInstanceSize([p class]),malloc_size((__bridge const void *)(p))); 

打印結果:

由以上打印結果可以看出 class_getInstanceSize 和 malloc_size 獲取到的內存大小不一樣,那么是什么導致的兩者獲取同一對象的內存大小不一樣呢?我們下一步繼續探索。

首先我們先手動計算一下這個對象所占的內存:

  • isa -- 8字節
  • name -- 8字節
  • age -- 4字節
  • height -- 8字節
  • hobby -- 8字節
  • 總計 36 字節。

我們跟蹤 objc 源碼可以發現改變 size 的地方有兩個地方:

  • instanceSize 繼續跟蹤

1.instanceSize

  1. size_t instanceSize(size_t extraBytes) const { 
  2.         if (fastpath(cache.hasFastInstanceSize(extraBytes))) { 
  3.             return cache.fastInstanceSize(extraBytes); 
  4.         } 
  5.  
  6.         size_t size = alignedInstanceSize() + extraBytes;// alignedInstanceSize 
  7.         // CF requires all objects be at least 16 bytes. 
  8.         if (size < 16) size = 16; 
  9.         return size
  10.  
  11. uint32_t alignedInstanceSize() const { 
  12.         return word_align(unalignedInstanceSize()); 
  13.  
  14. #   define WORD_MASK 7UL 
  15. static inline uint32_t word_align(uint32_t x) { 
  16.     return (x + WORD_MASK) & ~WORD_MASK; 

由以上源碼可以得到 instanceSize 使用 8 字節對齊原則處理 Size,并且最小為 16 字節。

2.calloc

由于 calloc 屬于 malloc 源碼里面

跟蹤 libmalloc 源碼:

calloc 源碼實現:

  1. void * 
  2. calloc(size_t num_items, size_t size
  3.     void *retval; 
  4.     retval = malloc_zone_calloc(default_zone, num_items, size); 
  5.     if (retval == NULL) { 
  6.         errno = ENOMEM; 
  7.     } 
  8.     return retval; 
  9.  
  10. // malloc_zone_calloc 
  11. void * 
  12.     malloc_zone_calloc(malloc_zone_t *zone, size_t num_items, size_t size
  13.     MALLOC_TRACE(TRACE_calloc | DBG_FUNC_START, (uintptr_t)zone, num_items, size, 0); 
  14.  
  15.     void *ptr; 
  16.     if (malloc_check_start && (malloc_check_counter++ >= malloc_check_start)) { 
  17.         internal_check(); 
  18.     } 
  19.  
  20.     ptr = zone->calloc(zone, num_items, size); 
  21.      
  22.     if (malloc_logger) { 
  23.         malloc_logger(MALLOC_LOG_TYPE_ALLOCATE | MALLOC_LOG_TYPE_HAS_ZONE | MALLOC_LOG_TYPE_CLEARED, (uintptr_t)zone, 
  24.                 (uintptr_t)(num_items * size), 0, (uintptr_t)ptr, 0); 
  25.     } 
  26.  
  27.     MALLOC_TRACE(TRACE_calloc | DBG_FUNC_END, (uintptr_t)zone, num_items, size, (uintptr_t)ptr); 
  28.     return ptr; 

斷點打印 zone->calloc

  • ①:得到其真實調用為 default_zone_calloc
  • ②:搜索 default_zone_calloc 繼續跟進,打印 default_zone_calloc 內部的 zone->calloc 得到 nano_calloc
  • ③:分析 nano_calloc 源碼可以知道在 _nano_malloc_check_clear 內進行了相關操作
  1. static void * 
  2. default_zone_calloc(malloc_zone_t *zone, size_t num_items, size_t size
  3.     zone = runtime_default_zone(); 
  4.      
  5.     return zone->calloc(zone, num_items, size); 
  6.  
  7. static void * 
  8. nano_calloc(nanozone_t *nanozone, size_t num_items, size_t size
  9.     size_t total_bytes; 
  10.  
  11.     if (calloc_get_size(num_items, size, 0, &total_bytes)) { 
  12.         return NULL
  13.     } 
  14.  
  15.     if (total_bytes <= NANO_MAX_SIZE) { 
  16.         void *p = _nano_malloc_check_clear(nanozone, total_bytes, 1); 
  17.         if (p) { 
  18.             return p; 
  19.         } else { 
  20.             /* FALLTHROUGH to helper zone */ 
  21.         } 
  22.     } 
  23.     malloc_zone_t *zone = (malloc_zone_t *)(nanozone->helper_zone); 
  24.     return zone->calloc(zone, 1, total_bytes); 

跳轉到 _nano_malloc_check_clear 內部發現代碼很多,一臉懵逼,但是仔細一看很多都是做一些容錯判斷,除去這些代碼后,返現與size 有關的只有一行代碼:

  1. size_t slot_bytes = segregated_size_to_fit(nanozone, size, &slot_key); 

跳轉進 segregated_size_to_fit 可以看到又是內存對齊的代碼,這里的內存對齊是以16字節原則進行對齊的。

  1. #define SHIFT_NANO_QUANTUM      4 
  2. #define NANO_REGIME_QUANTA_SIZE (1 << SHIFT_NANO_QUANTUM)   // 16 
  3.  
  4. static MALLOC_INLINE size_t 
  5. segregated_size_to_fit(nanozone_t *nanozone, size_t size, size_t *pKey) 
  6.     size_t k, slot_bytes; 
  7.  
  8.     if (0 == size) { 
  9.         size = NANO_REGIME_QUANTA_SIZE; // Historical behavior 
  10.     } 
  11.     k = (size + NANO_REGIME_QUANTA_SIZE - 1) >> SHIFT_NANO_QUANTUM; // round up and shift for number of quanta 
  12.     slot_bytes = k << SHIFT_NANO_QUANTUM;                           // multiply by power of two quanta size 
  13.     *pKey = k - 1;                                                  // Zero-based! 
  14.  
  15.     return slot_bytes; 

總結

經過上述的各種分析,我們可以得到的結論是 instanceSize 是以 8 字節進行對齊的, 后面 calloc 是以 16 字節進行對齊的,說明 calloc 進一步對對象進行了處理。也就解釋了我們打印出來的 40-48 了。

 

由以上可以知道對象申請的內存大小和系統開辟的大小存在不一致的情況,8 字節對齊應用于對象的屬性,16 字節對齊應用于對象,由于對象的內存是連續的,這樣可以規避一些不必要的風險,以空間換時間來得到更高的安全性。

 

責任編輯:武曉燕 來源: 網羅開發
相關推薦

2021-08-06 11:50:49

Linux 字節對齊Linux 系統

2021-08-16 06:56:21

Slice數組類型內存

2021-12-16 06:52:33

C語言內存分配

2022-11-30 08:19:15

內存分配Go逃逸分析

2021-01-07 07:53:10

JavaScript內存管理

2018-03-27 10:06:26

對象存儲演進

2013-04-17 10:46:54

面向對象

2022-11-28 07:21:53

操作系統內存管理

2024-03-05 10:09:16

restfulHTTPAPI

2023-06-14 08:15:34

算法合并操作Winner

2024-12-09 08:18:33

2010-08-10 10:00:57

Flex內存

2021-05-19 08:04:11

ASP.Net服務性原則

2021-02-03 15:12:08

java內存溢出

2012-06-07 10:11:01

面向對象設計原則Java

2019-07-11 15:43:44

KVMKSM內存

2020-05-09 13:49:00

內存空間垃圾

2009-10-09 09:42:07

虛擬機內存

2022-12-12 08:42:06

Java對象棧內存

2021-03-28 13:54:31

操作系統內存管理
點贊
收藏

51CTO技術棧公眾號

主站蜘蛛池模板: 亚洲欧美激情四射 | 日韩中文字幕区 | 青青操av| 在线播放中文字幕 | 欧美国产精品久久久 | 亚洲精选久久 | 先锋资源站 | 国产一区二区三区在线看 | 99精彩视频 | 一级片av | 在线看片网站 | 色偷偷噜噜噜亚洲男人 | 日韩羞羞 | 国产精品久久久久久久久久免费看 | 黄色免费在线观看网址 | 午夜精品久久久久久久久久久久久 | 久久久久国产精品 | 亚洲性爰| 男女精品久久 | 国产乱码精品一区二区三区忘忧草 | 日韩精品在线看 | 国产1区在线 | 国产一级视频在线播放 | 在线一区| 亚洲视频一区二区三区 | 成人看片在线观看 | 国产欧美精品一区二区三区 | 九九热精品在线 | 午夜影院网站 | 免费成人在线网站 | 国产精品国产a级 | 六月成人网 | 欧美一区视频 | 黄色激情毛片 | 99pao成人国产永久免费视频 | 亚洲视频在线观看 | 国产精品久久久久久一区二区三区 | 美女131mm久久爽爽免费 | 91社区在线观看高清 | 亚洲国产成人精品女人 | 99久视频|