【iOS】SideTable

文章目錄

    • 前言
    • 1??Side Table 的核心作用:擴展對象元數據存儲
      • 1.1 傳統對象的內存限制
      • 1.2 Side Table 的定位:集中式元數據倉庫
    • 2??Side Table 的底層結構與關聯
      • 2.1 Side Table 與 isa 指針的關系
      • 2.2 Side Table 的存儲結構
      • 2.3 SideTable 的工作流程
    • 3??SideTable 的典型應用場景
      • 3.1 弱引用(`__weak`)的實現
      • 3.2 關聯對象(Associated Objects)
      • 3.3 KVO(鍵值觀察)的實現
      • 3.4 引用計數的優化存儲
    • 4??SideTable特點
    • 總結

前言

在 iOS/macOS 的內存管理中,Side Table(邊表) 是蘋果為優化對象元數據存儲而設計的 輔助數據結構。它與對象的 isa 指針緊密關聯,用于存儲對象的額外信息(如引用計數、弱引用指針、關聯對象等),解決了傳統對象內存布局無法高效擴展的問題。它的設計與使用是OC運行時實現弱引用的基礎,使得ARC能夠正確地處理弱引用的生命周期。

1??Side Table 的核心作用:擴展對象元數據存儲

1.1 傳統對象的內存限制

OC 對象的內存布局以 isa 指針為核心(指向類對象),但僅靠 isa 無法存儲所有元數據:

  • 普通對象的 isa 指針僅指向類對象,無法直接存儲引用計數、弱引用等動態信息。
  • 若為每個對象單獨分配元數據內存,會導致內存碎片和性能下降。

1.2 Side Table 的定位:集中式元數據倉庫

Side Table 是 全局共享的哈希表(或數組),為需要額外元數據的對象提供統一的存儲空間。它的核心作用是:

  • 存儲對象的擴展元數據(如引用計數、弱引用指針、關聯對象鍵值對)。
  • 減少內存碎片:多個對象共享同一 Side Table 的存儲空間,避免為每個對象單獨分配內存。

2??Side Table 的底層結構與關聯

2.1 Side Table 與 isa 指針的關系

OC 對象的 isa 指針(Class 類型)在 64 位系統中被擴展為 uintptr_t 類型(無符號長整型),通過 位域(Bit Field) 存儲額外信息:

  • 低 48 位:指向類對象或 Side Table 的地址(具體取決于對象類型)。
  • 高 16 位:存儲標記位(如是否為 weak 對象、是否需要 Side Table 等)。
/*_arm64(對應ios移動端)*/ 
#     define ISA_MASK        0x0000000ffffffff8ULL
#     define ISA_MAGIC_MASK  0x000003f000000001ULL
#     define ISA_MAGIC_VALUE 0x000001a000000001ULL
#     define ISA_HAS_CXX_DTOR_BIT 1
#     define ISA_BITFIELD                                                     \uintptr_t nonpointer        : 1; /*是否使用非指針格式*/                                      \uintptr_t has_assoc         : 1; /*是否有關聯對象*/                                      \uintptr_t has_cxx_dtor      : 1; /*是否有C++析構函數*/                                      \uintptr_t shiftcls          : 33; /*MACH_VM_MAX_ADDRESS 0x1000000000*/ /*存儲類指針的核心字段(加密后)*/ \uintptr_t magic             : 6; /*??驗證指針合法性?? 調試器將提取的 magic_value 與預定義的合法值(ISA_MAGIC_VALUE)比較*/                                      \uintptr_t weakly_referenced : 1;  /*是否為弱飲用*/                                     \uintptr_t unused            : 1;  /*保留位(數據結構或協議中預留的未使用位)*/                                     \uintptr_t has_sidetable_rc  : 1;  /*是否使用弱引用表*/                                     \uintptr_t extra_rc          : 19  /*內聯引用計數(最大2^19-1)*/# elif __x86_64__ //__x86_64__(對應macos)(與上面一樣)
#   define ISA_MASK        0x00007ffffffffff8ULL
#   define ISA_MAGIC_MASK  0x001f800000000001ULL
#   define ISA_MAGIC_VALUE 0x001d800000000001ULL
#   define ISA_HAS_CXX_DTOR_BIT 1
#   define ISA_BITFIELD                                                        \uintptr_t nonpointer        : 1;                                         \uintptr_t has_assoc         : 1;                                         \uintptr_t has_cxx_dtor      : 1;                                         \uintptr_t shiftcls          : 44; /*MACH_VM_MAX_ADDRESS 0x7fffffe00000*/ \uintptr_t magic             : 6;                                         \uintptr_t weakly_referenced : 1;                                         \uintptr_t unused            : 1;                                         \uintptr_t has_sidetable_rc  : 1;                                         \uintptr_t extra_rc          : 8  /*(最大為2^8-1)*/

在上述isa的結構體代碼中,extra_rchas_sidetable_rc,這兩者共同記錄引用計數器。

關鍵邏輯
當對象需要存儲額外元數據時(如弱引用),isa 指針的高位會被標記為“需要 Side Table”,并通過低 48 位指向對應的 Side Table 條目。

2.2 Side Table 的存儲結構

Side Table 的底層實現是一個 全局的哈希表(或數組),每個條目對應一個對象的內存地址,存儲其擴展元數據。不同平臺(iOS/macOS)的實現略有差異,但核心結構相似:

字段描述
refcount引用計數(用于 ARC 管理)。
weak_refs弱引用指針數組(存儲指向該對象的弱引用變量地址)。
associated_objects關聯對象鍵值對(存儲通過 objc_setAssociatedObject 設置的關聯數據)。
flags標記位(如是否被標記為待釋放、是否為類對象等)。

在obj4-906中,sideTable部分的結構如下:

struct SideTable {spinlock_t slock;  //自旋鎖RefcountMap refcnts;  //引用計數映射表weak_table_t weak_table;  //弱引用表SideTable() {memset(&weak_table, 0, sizeof(weak_table));} //SideTable():構造函數,使用memeset將weak_table初始化為0,確保弱引用表的初始狀態安全。~SideTable() {_objc_fatal("Do not delete SideTable.");} //~SideTable():析構函數,調用 _objc_fatal("Do not delete SideTable.")防止手動釋放。SideTable的生命周期由 Objective-C 運行時管理(如對象銷毀時自動釋放),禁止用戶主動刪除。void lock() { slock.lock(); }void unlock() { slock.unlock(); }//直接操作自旋鎖 slock,用于保護對 refcnts和 weak_table的修改。void reset() { slock.reset(); }  //重置自旋鎖狀態(具體實現依賴 spinlock_t的底層邏輯,通常用于釋放鎖或重置為未鎖定狀態)。// Address-ordered lock discipline for a pair of side tables.template<HaveOld, HaveNew>static void lockTwo(SideTable *lock1, SideTable *lock2);template<HaveOld, HaveNew>static void unlockTwo(SideTable *lock1, SideTable *lock2);
};

slock是一個自旋鎖:保證對 SideTable中數據(如引用計數、弱引用表)的線程安全訪問。自旋鎖適用于臨界區較小的場景(引用計數修改通常很快),避免線程阻塞開銷。
請添加圖片描述
refcnts是引用計數映射表:存儲當前對象的引用計數值。RefcountMap本質是一個輕量級的哈希表或鍵值對結構,鍵為對象的內存地址(或唯一標識),值為對應的引用計數值。
請添加圖片描述

weak_table是弱引用表:存儲所有指向當前對象的弱引用指針(__weak修飾的指針)。弱引用表的核心功能是:當對象被釋放時,自動將所有弱引用置為 nil,避免野指針。

weak_table_t源碼結構如下:

/*** The global weak references table. Stores object ids as keys,* and weak_entry_t structs as their values.*/
struct weak_table_t {weak_entry_t *weak_entries;  //弱引用條目數組:指向 weak_entry_t結構體的指針數組。每個 weak_entry_t對應一個指向當前對象的 __weak指針,存儲弱引用的具體信息(如指針地址、對象狀態等)size_t    num_entries;  //弱引用條目數量:記錄當前 weak_table_t中有效弱引用條目的數量(即 weak_entries數組中實際使用的元素個數)uintptr_t mask;  //哈希掩碼:用于計算弱引用的哈希索引,優化哈希表的存儲和查找效率//弱引用的哈希值通常通過 hash ^ mask計算(hash是弱引用指針的哈希值),結果對齊到 weak_entries數組的大小。mask的值通常為數組大小減一(如數組大小為 2^n,則 mask = (1 << n) - 1),確保索引在數組范圍內uintptr_t max_hash_displacement;  //最大哈希位移
};

關于weak_entry_t,,其源碼在obj4_906中是這樣的:

#define WEAK_INLINE_COUNT 4
#define REFERRERS_OUT_OF_LINE 2
struct weak_entry_t {DisguisedPtr<objc_object> referent;union {struct {weak_referrer_t *referrers;  // 外聯弱引用指針數組(動態分配)uintptr_t        out_of_line_ness : 2;  // 標記為外聯存儲(固定為 1)uintptr_t        num_refs : PTR_MINUS_2;  // 弱引用數量(減去 2 位用于其他標記)uintptr_t        mask;  // 哈希掩碼(用于快速查找)uintptr_t        max_hash_displacement;  // 最大哈希位移(解決哈希沖突)};struct {// out_of_line_ness field is low bits of inline_referrers[1]weak_referrer_t  inline_referrers[WEAK_INLINE_COUNT];};bool out_of_line() {return (out_of_line_ness == REFERRERS_OUT_OF_LINE);}weak_entry_t& operator=(const weak_entry_t& other) {memcpy(this, &other, sizeof(other));return *this;}weak_entry_t(objc_object *newReferent, objc_object **newReferrer): referent(newReferent){inline_referrers[0] = newReferrer;for (int i = 1; i < WEAK_INLINE_COUNT; i++) {inline_referrers[i] = nil;}}
};

2.3 SideTable 的工作流程

由上述源碼,我們可以略微推斷出sideTable的工作流程:

  1. 對象創建:當對象大小超過小對象閾值時,運行時為其分配 SideTable,并將引用計數初始化為 1(retainCount)。
  2. 引用計數修改:調用 retain/release時,運行時通過對象的 isa指針找到對應的 SideTable,加鎖后修改 refcnts中的計數值。
  3. 弱引用注冊:當對象被 __weak指針指向時,運行時將其弱引用指針注冊到 SideTableweak_table中。
  4. 對象釋放:當引用計數減至 0 時,運行時觸發 dealloc,遍歷 weak_table將所有弱引用置為 nil,然后釋放 SideTable關聯的資源(如 refcntsweak_table內存)。

3??SideTable 的典型應用場景

3.1 弱引用(__weak)的實現

__weak 修飾的變量不會增加對象的引用計數,但需在對象釋放時自動置空。Side Table 是其核心實現載體:

流程

  1. 當對象被 __weak 變量引用時,系統會在 Side Table 中為該對象創建條目。
  2. __weak 變量的值存儲為 Side Table 條目的索引(而非直接存儲對象地址)。
  3. 對象釋放時,通過 Side Table 找到所有指向它的 __weak 變量,并將其置空。

3.2 關聯對象(Associated Objects)

通過 objc_setAssociatedObjectobjc_getAssociatedObject 設置的關聯對象,其數據實際存儲在 Side Table 中:

示例

// 為 NSObject 實例添加關聯對象(鍵為 "com.example.name")
NSString *name = @"張三";
objc_setAssociatedObject(obj, (__bridge const void *)(@"com.example.name"), name, OBJC_ASSOCIATION_RETAIN_NONATOMIC);// 從 Side Table 中讀取關聯對象
NSString *storedName = objc_getAssociatedObject(obj, (__bridge const void *)(@"com.example.name"));

底層邏輯
關聯對象的鍵(如 @"com.example.name")和值會被存儲在 Side Table 的 associated_objects 字段中,鍵通過哈希映射快速查找。

3.3 KVO(鍵值觀察)的實現

KVO 的核心是 動態生成子類 并重寫 setter 方法,但觀察者列表(observers)的存儲依賴 Side Table:

流程

  1. 當對對象屬性添加 KVO 觀察時,系統會生成一個該對象的子類(如 NSKVONotifying_Obj)。
  2. 子類的 isa 指針指向 Side Table 中的觀察者列表條目。
  3. 屬性值變化時,通過 Side Table 找到所有觀察者并觸發通知。

3.4 引用計數的優化存儲

ARC 下,對象的引用計數(retainCount)不再直接存儲在對象內存中,而是通過 Side Table 的 refcount 字段統一管理:

  • 引用計數增加(retain)時,更新 Side Table 中的 refcount
  • 引用計數減少(release)時,檢查 refcount 是否為 0,若為 0 則觸發對象釋放。

4??SideTable特點

  • 內存布局:緊湊高效

SideTable 的條目(Entry)在內存中是 連續存儲 的,通過哈希表快速查找。每個條目的大小根據存儲內容動態調整(如僅存儲弱引用時,條目較小;存儲關聯對象時,條目較大)。

  • 線程安全:鎖保護

Side Table 的讀寫需保證線程安全,蘋果通過 自旋鎖(Spin Lock)信號量(Semaphore) 實現:修改 Side Table(如添加/刪除條目)時加鎖;讀取 Side Table(如獲取弱引用列表)時加鎖或使用無鎖讀取(CAS 操作)。

  • 版本演進:從 __objc_sideTableobjc_sideTable

早期 iOS 版本(如 iOS 9 前)使用 __objc_sideTable 結構體,存儲方式為數組;iOS 10 后優化為哈希表(objc_sideTable),提升了查找效率。

總結

Side Table 是 iOS 內存管理的“元數據中心”,通過集中存儲對象的擴展信息(引用計數、弱引用、關聯對象等),解決了傳統對象內存布局的局限性。它的存在讓 OC 能夠高效支持 ARC、弱引用、KVO 等高級特性,是蘋果內存管理優化的關鍵技術之一。

本文來自互聯網用戶投稿,該文觀點僅代表作者本人,不代表本站立場。本站僅提供信息存儲空間服務,不擁有所有權,不承擔相關法律責任。
如若轉載,請注明出處:http://www.pswp.cn/web/90534.shtml
繁體地址,請注明出處:http://hk.pswp.cn/web/90534.shtml
英文地址,請注明出處:http://en.pswp.cn/web/90534.shtml

如若內容造成侵權/違法違規/事實不符,請聯系多彩編程網進行投訴反饋email:809451989@qq.com,一經查實,立即刪除!

相關文章

【Spring Cloud Gateway 實戰系列】高級篇:服務網格集成、安全增強與全鏈路壓測

一、服務網格集成&#xff1a;Gateway與Istio的協同作戰在微服務架構向服務網格演進的過程中&#xff0c;Spring Cloud Gateway可與Istio形成互補——Gateway負責南北向流量&#xff08;客戶端到集群&#xff09;的入口管理&#xff0c;Istio負責東西向流量&#xff08;集群內服…

一文說清楚Hive

Hive作為Apache Hadoop生態的核心數據倉庫工具&#xff0c;其設計初衷是為熟悉SQL的用戶提供大規模數據離線處理能力。以下從底層計算框架、優點、場景、注意事項及實踐案例五個維度展開說明。 一、Hive底層分布式計算框架對比 Hive本身不直接執行計算&#xff0c;而是將HQL轉換…

SeaweedFS深度解析(三):裸金屬單機和集群部署

#作者&#xff1a;閆乾苓 文章目錄2.2.4 S3 Server&#xff08;兼容 Amazon S3 的接口&#xff09;2.2.5 Weed&#xff08;命令行工具&#xff09;3、裸金屬單機和集群部署3.1 裸金屬單機部署3.1.1安裝 SeaweedFS3.1.2 以Master模式啟動2.2.4 S3 Server&#xff08;兼容 Amazon…

相機ROI 參數

相機的 ROI&#xff08;Region of Interest&#xff0c;感興趣區域&#xff09; 參數&#xff0c;是指通過設置圖像傳感器上 特定區域 作為有效成像區域&#xff0c;從而只采集該區域的圖像數據&#xff0c;而忽略其他部分。這一功能常用于工業相機、科研相機、高速相機等場景&…

Vue基礎(24)_VueCompinent構造函數、Vue實例對象與組件實例對象

分析上一節代碼中的school組件&#xff1a;該組件是一個名為VueCompinent的構造函數。截取部分vue.js源碼&#xff0c;分析Vue.extend&#xff1a;// 定義一個名為VueComponent的構造函數對象Sub&#xff0c;往Sub對象調用_init(options)方法&#xff0c;參數為配置項&#xff…

螢石云替代產品攝像頭方案螢石云不支持TCP本地連接-東方仙盟

不斷試錯東方仙盟深耕科研測評&#xff0c;聚焦前沿領域&#xff0c;以嚴謹標準評估成果&#xff0c;追蹤技術突破&#xff0c;在探索與驗證中持續精進&#xff0c;為科研發展提供參考&#xff0c;助力探路前行 螢石云價格螢石云的不便于使用 家庭場景&#xff1a;成本可控與隱…

C51:用DS1302時鐘讀取和設置時間

因為在ds1302.c文件中包含了寫ds1302&#xff08;51向ds1302寫數據&#xff09;和讀ds1302&#xff08;51從ds1302讀數據&#xff09;的兩個函數&#xff0c;我們根據文件中提供的函數來寫讀取時間和設置時間的函數即可ds1302.c文件源碼如下&#xff0c;需要的同學可以參考一下…

webrtc整體架構

WebRTC&#xff08;Web Real-Time Communication&#xff09;是一套支持瀏覽器和移動應用進行實時音視頻通信的開源技術標準&#xff0c;其架構設計圍繞 “實時性”“低延遲”“跨平臺” 和 “安全性” 展開&#xff0c;整體可分為核心引擎層、API 層、支撐服務層三大部分&…

淺析PCIe 6.0 ATS地址轉換功能

在現代高性能計算和虛擬化系統中,地址轉換(Address Translation)是一個至關重要的機制。隨著 PCIe 設備(如 GPU、網卡、存儲控制器)直接訪問系統內存的能力增強,設備對虛擬內存的訪問需求日益增長。 為了提升性能并確保安全訪問,Address Translation Services(ATS) 應…

【前端】ikun-pptx編輯器前瞻問題二: pptx的壓縮包結構,以及xml正文樹及對應元素介紹

文章目錄PPTX文件本質&#xff1a;一個壓縮包核心文件解析1. 幻燈片內容文件 (ppt/slides/slideX.xml)2. 元素類型解析文本框元素 (p:sp)圖片元素 (p:pic)單位系統開發注意事項參考工具pptx渲染路線圖PPTX文件本質&#xff1a;一個壓縮包 PPTX文件實際上是一個遵循Open XML標準…

分布式任務調度實戰:XXL-JOB與Elastic-Job深度解析

告別傳統定時任務的局限&#xff0c;擁抱分布式調度的強大與靈活 在現代分布式系統中&#xff0c;高效可靠的任務調度已成為系統架構的核心需求。面對傳統方案&#xff08;如Timer、Quartz&#xff09;在分布式環境下的不足&#xff0c;開發者急需支持集群調度、故障轉移和可視…

Windows 11下純軟件模擬虛擬機的設備模擬與虛擬化(僅終端和網絡)

Windows 11下用GCC的C代碼實現的虛擬機需要終端輸入/輸出&#xff08;如串口或虛擬控制臺&#xff09;和網絡連接&#xff0c;但不需要完整的硬件設備&#xff08;如磁盤、顯卡、USB 等&#xff09;。在終端輸入/輸出方面&#xff0c;參考qemu的源代碼&#xff0c;但不調用qemu…

CCF-GESP 等級考試 2025年6月認證Python六級真題解析

1 單選題&#xff08;每題 2 分&#xff0c;共 30 分&#xff09;第1題 下列哪一項不是面向對象編程&#xff08;OOP&#xff09;的基本特征&#xff1f;&#xff08; &#xff09;A. 繼承 (Inheritance) B. 封裝 (Encapsul…

C++中的deque

1. 什么是 Deque&#xff1f; 核心概念&#xff1a; Deque 是 “Double-Ended Queue”&#xff08;雙端隊列&#xff09;的縮寫。你可以把它想象成一個可以在兩端&#xff08;頭部和尾部&#xff09;高效地進行添加或刪除操作的線性數據結構。關鍵特性&#xff1a; 雙端操作&am…

GNU到底是什么,與Unix和Linux是什么關系

GNU&#xff08;發音為 /ɡnu?/&#xff0c;類似“革奴”&#xff09;是一個自由軟件操作系統項目&#xff0c;由理查德斯托曼&#xff08;Richard Stallman&#xff09;于1983年發起&#xff0c;目標是創建一個完全由自由軟件組成的類Unix操作系統。它的名字是一個遞歸縮寫&a…

雙指針算法介紹及使用(下)

在上一篇文章中我們已經對雙指針有了一定了解&#xff0c;接下來我們通過題目來對雙指針進行更好的理解。 1. leetcode 202. 快樂數 這道題使用的方法是快慢指針&#xff0c; 比如說一個數X&#xff0c;那么創建兩個變量X1和X2&#xff0c;然后X1每次變化兩次&#xff0c;X2變化…

Elasticsearch整合:Repository+RestClient雙模式查詢優化

Elasticsearch整合&#xff1a;RepositoryRestClient雙模式查詢優化Elasticsearch 雙模式查詢優化&#xff1a;Repository RestClient 整合指南一、架構設計&#xff1a;雙模式協同工作流二、Repository 模式&#xff1a;快速開發最佳實踐2.1 基礎配置2.2 高級特性&#xff1a…

Elasticsearch 高級查詢語法 Query DSL 實戰指南

目錄 1、DSL 概述 1.1 DSL按照查詢的結構層次劃分 1.2 DSL按照檢索功能的用途和特性劃分 1.3 示例數據準備 2、match_all ——匹配所有文檔 3、精確匹配 3.1 term——單字段精確匹配查詢 3.2 terms——多值精確匹配 3.3 range——范圍查詢 3.4 exists——是否存在查詢…

DNS 服務正反向解析與 Web 集成實戰:從配置到驗證全流程

DNS 服務正反向解析配置全流程指南 一、前言 在網絡環境中&#xff0c;DNS&#xff08;Domain Name System&#xff09;服務起著至關重要的作用&#xff0c;它負責將域名解析為 IP 地址&#xff0c;以及將 IP 地址反向解析為域名。本文將詳細介紹如何配置 DNS 服務的正反向解析…

2025.07.25【宏基因組】|PathoScope 安裝與使用指南

PathoScope 安裝與使用指南&#xff1a;微生物組數據分析利器 作為一名生物信息工程師&#xff0c;在微生物組數據分析中&#xff0c;我們常常需要高效、準確的工具來鑒定和量化樣本中的微生物組成。PathoScope 正是這樣一款強大的工具&#xff0c;它能夠幫助我們從高通量測序…