記憶體管理相關 記憶體布局 記憶體管理方案

2021-10-20 17:55:13 字數 2856 閱讀 4984

ios系統下的記憶體布局

最上面是核心區,最下面是保留區,中間是給程式載入的空間。

從高位址到低位址依次為核心區、棧、堆、靜態全域性區(未初始化區域.bss和已初始化區域.data)、**區、保留區;

程式被載入到記憶體分成三段未初始化資料(.bss)、已初始化資料(.data)和**段(.text)。

**段顧名思義存放**;

已初始化區域:已經初始化宣告的靜態變數和全域性變數;

未初始化區域:未初始化的靜態變數和全域性變數;

堆heap:建立的物件或被copy的block;

記憶體管理方案

ios管理系統針對不同的場景提供不同的記憶體管理方案。

·taggedpointer:對一些小物件使用,如nsnumber

·nonpointer_isa:非指標型的isa;應用於64位架構下的ios應用程式。在64位架構下,isa指標佔64個位元位,實際上有32位或者40位就夠用了,剩餘的位元位就浪費了。為了不讓記憶體浪費更好的管理記憶體,剩餘的32位蘋果用來儲存和記憶體管理相關的內容。

·雜湊表:是乙個複雜的資料結構,其中包含了引用計數表和弱引用表。

【詳解nonpointer_isa】

在64位架構下:

第一位has_assoc表示當前物件是否有關聯物件,0表示沒有,1表示有。

第二位has_cxx_dtor代表當前物件是否有c++**

第三位 3···31、32···35到第35位共33位,表示當前物件的類物件的記憶體位址。

第36···41位共6位,是magic 字段。

第42位weakly_referenced表示是否含有弱引用指標。

第43位deallocating表示當前指標是否正在進行dealloc操作。

第44位has_sidetable_rc表示當前isa指標的引用計數是否達到上限,如果達到上限需要外掛程式乙個sidetable,來額外儲存相關的引用計數內容。

第45···63位extra_rc表示額外的引用計數,儲存記憶體管理相關的,當引用計數很小的時候,就直接存在isa指標當中。

如下圖:  

【詳解sidetable】

雜湊表是通過sidetables()結構來實現的,sidetables下面掛了很多sidetable,在不同的架構下是有不同個數的,比如說在非嵌入式系統中sidetable有64個。

sidetables()實際上是乙個雜湊表(hash),可以通過它的物件指標,找到它對應的引用計數表或者弱引用表具體在哪個sidetable中。

sidetable有自旋鎖(spinlock_t),引用計數表(refcountmap)和弱引用表(weak_table_t)。

sidetable結構:

自旋鎖:是忙等的鎖。如果鎖已經被其他執行緒獲取,那麼當前執行緒會自己去不斷的獲取是否被釋放,直到其他執行緒釋放。適用於輕量訪問。如+1,-1。

引用計數表:是hash表,其實就是hash查詢,插入和查詢通過同乙個hash函式,避免了迴圈遍歷,提高了查詢效率。

size_t實際上是乙個無符號long型(unsign long)的變數。在獲取物件的真實的引用計數值時,需要向右偏移兩位。

弱引用表:weak_table_t也是乙個hash表。

思考如下問題:

為什麼不是乙個sidetable?而是有多個sidetable組成乙個sidetables;或者說sidetables為什麼是多張表,而不是一張表?

解析:假設只有一張sidetable表,那麼記憶體中的所有物件的引用計數或者弱引用都儲存在這張表中,這個時候,如果我們要對某乙個物件的引用計數值進行操作,+1或者-1;由於不同的物件在不同的執行緒中,不同的執行緒操作同一張表,就有資源訪問的問題,那麼我們要對這張大表進行加鎖操作來保證資料訪問的安全性。在這個過程中就會產生乙個效率問題,比如,成千上萬的物件進行引用計數操作,那麼需要加鎖排隊,就會有效率問題。比如,現在已經有乙個物件在操作這個大表,那麼下個物件就要等前物件操作結束,把鎖釋放之後,它才能操作這張表。系統為了解決這種效率問題,引入了分離鎖。分離鎖就是把乙個大表分成幾個小表,a、b分別在不同表中,同時進行操作的話,可以併發進行,這樣就提高了訪問效率。

思考如下問題:

怎樣實現快速分流?找到當前物件在哪張表中?【快速分流指給出乙個物件的指標,如何快速的定位到這個這個物件在哪張表中】

解析:sidetables本質是一張hash表。

什麼是hash表?有乙個指標物件key,通過hash函式的運算,得到乙個值value,找到對應的sidetable。

思考如下問題:

你是否使用過自旋鎖,自旋鎖和普通鎖有什麼區別?適用於哪些場景?

解析:自旋鎖是忙等的鎖,適用於輕量訪問。

思考如下問題:

引用計數表示通過什麼實現的?為什麼引用計數表要用hash表來實現呢?

解析:是通過hash表實現的。插入和查詢都通過同乙個hash函式,避免了迴圈遍歷,提高了查詢效率。

關於記憶體管理的討論全部基於objc-runtime-680版本講解。

《記憶體管理》 記憶體

1.c c 記憶體分布 我們先來看下面的一段 和相關問題 int globalvar 1 static int staticglobalvar 1 void test char char2 abcd char pchar3 abcd int ptr1 int malloc sizeof int 4 ...

記憶體管理 記憶體管理概述

儲存器的發展方向是高速 大容量和小體積,即儲存器嘗試更高讀寫速度,更大儲存容量,更小物理體積。在計算機中,常見的儲存器有 暫存器,快取,記憶體,硬碟,一般硬碟之類的輔助儲存器又稱外存。在平均讀寫速度上,有 暫存器 快取 記憶體 外存 在單位容量 上,有 外存 記憶體 快取 暫存器 cpu處理器只能直...

記憶體管理相關函式

記憶體分配及釋放相關函式 void calloc int num,int size 在記憶體中動態地分配 num 個長度為 size 的連續空間,並將每乙個位元組 共num size 個 都初始化為 0。void malloc int num 在堆區分配一塊指定大小的記憶體空間,用來存放資料。這塊記...