1. 程式人生 > >Objective-C記憶體佈局

Objective-C記憶體佈局

1.什麼叫記憶體佈局?

程式是由資料和方法組成的,執行程式則需要記憶體承載,記憶體是如何承載程式中的資料和方法的,就描述了程式執行時的記憶體結構,即記憶體佈局。

可見,討論記憶體佈局的具體細節需要在執行時。

2.C執行文記憶體佈局


解釋:

程式程式碼區(code area)

存放函式體的二進位制程式碼

靜態資料區(data area)

也稱全域性資料區,包含的資料型別比較多,如全域性變數、靜態變數、一般常量、字串常量。其中:
全域性變數和靜態變數的儲存是放在一塊的,初始化的全域性變數和靜態變數在一塊區域, 未初始化的全域性變數和未初始化的靜態變數在相鄰的另一塊區域。
常量資料(一般常量、字串常量)存放在另一個區域。
注意:靜態資料區的記憶體在程式結束後由作業系統釋放。

堆區(heap area)


一般由程式設計師分配和釋放,若程式設計師不釋放,程式執行結束時由作業系統回收。malloc()、calloc()、free()等函式操作的就是這塊記憶體。
注意:這裡所說的堆區與資料結構中的堆不是一個概念,堆區的分配方式倒是類似於連結串列。

棧區(stack area)


由系統自動分配釋放,存放函式的引數值、區域性變數的值等。其操作方式類似於資料結構中的棧。

命令列引數區


存放命令列引數和環境變數的值,如通過main()函式傳遞的值。

以一個例項圖來看:



C語言的記憶體佈局相對簡單,但也是最基本的。在編譯過程中就已經確定了所有函式的地址(偏移地址)。
C語言沒有物件的概念,那麼變數的佈局非常簡單,固定。除去全域性,靜態的變數分配在靜態資料區,其它的臨時變數,引數等,要麼分配在棧區由系統自動管理,要麼由malloc()、calloc()、free()等函式由程式設計師管理分配在堆區。而變數本身的空間大小,在分配時是相對簡單並可以確定的

3.Objective-C的記憶體佈局

在Objective-C中任何的類定義都是物件。即在程式啟動的時候任何類定義都對應於一塊記憶體。在編譯的時候,編譯器會給每一個類生成一個且只生成一個”描述其定義的物件”,也就是類物件(class object),他是一個單例(singleton), 而我們在C++等語言中所謂的物件,叫做例項物件(instance object)。對於例項物件我們不難理解,但類物件(class object)是幹什麼吃的呢?我們知道Objective-C是門很動態的語言,因此程式裡的所有例項物件(instace objec)都是在執行時由Objective-C的執行時庫生成的,而這個類物件(class object)就是執行時庫用來建立例項物件(instance object)的依據。

所以任何直接或間接繼承了NSObject的類,它的例項物件(instacne objec)中都有一個isa指標,指向它的類物件(class object)。這個類物件(class object)中儲存了關於這個例項物件(instace object)所屬的類結構資訊,包括定義的方法,遵守的協議等等

以上可以看到如果要討論OC中的內部佈局,就要討論兩種佈局:例項物件的記憶體佈局、例項物件所屬的類物件(Class)的記憶體佈局

一言以蔽之,例項變數(包括父類)都儲存在物件本身的儲存空間內;本類的例項方法儲存在類物件中,本類的類方法儲存在元類物件中;父類的例項方法儲存在各級 super class 中,父類的類方法儲存在各級 super meta class 中:


3.1例項物件的記憶體佈局

isa 指向其類物件,其餘空間儲存各級的 ivar


3.2類物件的記憶體佈局

(詳細可看 runtime.h 中對 objc_class 的定義),isa 指向其元類,super_class指向其父類,此外還包含例項變數列表、方法列表、協議列表:


通過以上分析,可以更好的理解和運用Runtime框架來解決Objective-C的動態問題。