這幾天看了些關(guān)于內(nèi)存布局的文章,發(fā)帖總結(jié)摘錄下重點(diǎn)。
C語(yǔ)言的內(nèi)存模型

程序代碼區(qū)(code area)
存放函數(shù)體的二進(jìn)制代碼
靜態(tài)數(shù)據(jù)區(qū)(data area)
也稱全局?jǐn)?shù)據(jù)區(qū),包含的數(shù)據(jù)類型比較多,如全局變量、靜態(tài)變量、一般常量、字符串常量。其中:
- 全局變量和靜態(tài)變量的存儲(chǔ)是放在一塊的,初始化的全局變量和靜態(tài)變量在一塊區(qū)域, 未初始化的全局變量和未初始化的靜態(tài)變量在相鄰的另一塊區(qū)域。
- 常量數(shù)據(jù)(一般常量、字符串常量)存放在另一個(gè)區(qū)域。
注意:靜態(tài)數(shù)據(jù)區(qū)的內(nèi)存在程序結(jié)束后由操作系統(tǒng)釋放。
堆區(qū)(heap area)
一般由程序員分配和釋放,若程序員不釋放,程序運(yùn)行結(jié)束時(shí)由操作系統(tǒng)回收。malloc()、calloc()、free()等函數(shù)操作的就是這塊內(nèi)存。
注意:這里所說(shuō)的堆區(qū)與數(shù)據(jù)結(jié)構(gòu)中的堆不是一個(gè)概念,堆區(qū)的分配方式倒是類似于鏈表。
棧區(qū)(stack area)
由系統(tǒng)自動(dòng)分配釋放,存放函數(shù)的參數(shù)值、局部變量的值等。其操作方式類似于數(shù)據(jù)結(jié)構(gòu)中的棧。
命令行參數(shù)區(qū)
存放命令行參數(shù)和環(huán)境變量的值,如通過(guò)main()函數(shù)傳遞的值。


C語(yǔ)言的內(nèi)存布局相對(duì)簡(jiǎn)單,但也是最基本的。在編譯過(guò)程中就已經(jīng)確定了所有函數(shù)的地址(偏移地址)。
C語(yǔ)言沒(méi)有對(duì)象的概念,那么變量的布局非常簡(jiǎn)單,固定。除去全局,靜態(tài)的變量分配在靜態(tài)數(shù)據(jù)區(qū),其它的臨時(shí)變量,參數(shù)等,要么分配在棧區(qū)由系統(tǒng)自動(dòng)管理,要么由malloc()、calloc()、free()等函數(shù)由程序員管理分配在堆區(qū)。而變量本身的空間大小,在分配時(shí)是相對(duì)簡(jiǎn)單并可以確定的。
C++對(duì)象的內(nèi)存布局
C++語(yǔ)言在C的基礎(chǔ)上添加了面向?qū)ο蟮母拍?,引入了封裝,繼承,多態(tài)。而一個(gè)對(duì)象的內(nèi)存布局就相對(duì)于C語(yǔ)言的結(jié)構(gòu)體等在內(nèi)存的布局要復(fù)雜的多。
在C++中,有兩種數(shù)據(jù)成員(class data members):static 和nonstatic,以及三種類成員函數(shù)(class member functions):static、nonstatic和virtual:

現(xiàn)在我們有一個(gè)類Base,它包含了上面這5中類型的數(shù)據(jù)或函數(shù):
class Base
{
public:
Base(int i) :baseI(i){};
int getI(){ return baseI; }
static void countI(){};
virtual void print(void){ cout << "Base::print()"; }
virtual ~Base(){}
private:
int baseI;
static int baseS;
};


可以看到,對(duì)一個(gè)C++對(duì)象來(lái)說(shuō),它的內(nèi)存布局僅有虛表指針和非靜態(tài)成員,而其他的靜態(tài)成員,成員函數(shù)(靜態(tài),非靜態(tài)),虛表等都是布局在類上的。
當(dāng)然,這是沒(méi)有考慮繼承的情況。繼承情況下會(huì)更復(fù)雜一些。可以參考(http://www.cnblogs.com/QG-whz/p/4909359.html)
OC對(duì)象的內(nèi)存布局
OC對(duì)象的內(nèi)存布局相對(duì)于C++更為復(fù)雜一些,出現(xiàn)了元類的概念:

簡(jiǎn)單來(lái)說(shuō),最左邊的是對(duì)象(Instance),中間的是類(Class),最右邊的是元類(Meta Class)。屬性(包括父類)都保存在對(duì)象本身的存儲(chǔ)空間內(nèi);本類的實(shí)例方法保存在類中,本類的類方法保存在元類中。
那么對(duì)象的內(nèi)存布局如下:isa 指針指向其類,其余空間保存各級(jí)的屬性(ivar)

而類的內(nèi)存布局如下:
struct objc_class
{
struct objc_class* isa;
struct objc_class* super_class;
const char* name;
long version;
long info;
long instance_size;
struct objc_ivar_list* ivars;
struct objc_method_list** methodLists;
struct objc_cache* cache;
struct objc_protocol_list* protocols;
};
isa 指針指向其元類,super_class指針指向其父類,此外還包含實(shí)例變量列表、方法列表、協(xié)議列表。
這里特別要指出的是實(shí)例變量列表中的實(shí)例變量的定義如下,它包含了變量的名稱、類型、偏移等,但卻不包括變量的值-----值在對(duì)象而非類中:
struct objc_ivar {
char *ivar_name OBJC2_UNAVAILABLE;
char *ivar_type OBJC2_UNAVAILABLE;
int ivar_offset OBJC2_UNAVAILABLE;
#ifdef __LP64__
int space OBJC2_UNAVAILABLE;
#endif
}
參考文章:
C語(yǔ)言的代碼內(nèi)存布局詳解
C語(yǔ)言內(nèi)存模型
圖說(shuō)C++對(duì)象模型:對(duì)象內(nèi)存布局詳解
c++的類的內(nèi)存布局
OC優(yōu)缺點(diǎn)
OC對(duì)象的內(nèi)存布局
Objetive-C內(nèi)存布局