Linux C的可執行檔案結構以及程序結構
(公共部分):程式碼區,BSS區,資料區.
1.程式碼區:存放可執行的指令.順便規劃局部變數的相關資訊(??).
獨有性:一份指令在記憶體(不管虛擬記憶體還是實際)中只要有一份就可以的
只讀性:彙編指令包含 操作碼+運算元;一般操作碼是不可變的,但是運算元可以改變.
而且有不同的定址方式.
立即數 | 資料包含在指令區 |
區域性資料 | 執行時在棧中分配,然後在指令中引用地址 |
BSS區,資料區 | 同上在,指令中引用"物件"的地址. |
2靜態區:
1.函式外的已初始化全域性變數(包括函式外部靜態變數).
2.靜態變數.
至於static的訪問許可權問題老生長談:1.靜態變數執行時不會被"釋放"2.static限定本檔案訪問.
3未初始化變數區(BSS Block Started by Symbol)
未初始化的全域性變數和靜態變數.特點:被系統自動置NULL的指標(引用型別),或者被置0的基本數字型別.
在被載入到記憶體中執行的時候,以上三段都賦予了不同的特點.
程式碼段 | 由載入器確定,一般是由OS支援的,如果在OS外,要手動指定載入位置了.試想一下ueft和boot程式的記憶體位置是沒有OS支援的. |
靜態區 | 生命週期為程式進入記憶體到釋放整個階段 |
BSS區 | 同靜態區 |
棧 |
區域性變數,函式引數值,返回值等等. Note:在堆疊出棧(函式執行結束)時失效,這就是為啥函式內變數不能被作用域外使用 以及 進行(地址引用:野指標的生產大戶) 管理者:編譯器管理. 特性:線性地址(地址連續,都有唯一前驅後繼) |
堆 |
用於動態分配記憶體.BSS區和棧區之間. 一般由User分配和釋放.(Java只由自己分配,釋放交JVM) 特性:非線性,可能產生記憶體碎片. |
這樣分配的原因:
1.程式碼和資料分開,可以在哈弗架構下的CPU更高效.Code-Cache-Bus與Data-Cache-Bus分開並行工作.
2.同上,即使在馮諾依曼結構下,程式碼執行也是PC自加進行的.如果混編會破壞Code地址的線性特性,降低效率,(定位陣列和連結串列那個更快?)
3.臨時變數生命週期短,放在棧中有效提高效率.
4.堆可以使程式更具有靈活性.
配合修飾符
(懶得打字了直接上圖)
全域性變數,函式在外使用的方法:
1.標頭檔案中定義:可能會產生重複定義(在連結階段*.o-->elf檔案時候).因為標頭檔案在處理的時候是copy到*.c/*.cc/*.cpp檔案內的,在編譯階段每個檔案(*.o)都會生成一個"該識別符號",而且作用域是整個工程.
2.extern定義: