C 虛擬位址空間與編譯鏈結原理

2021-09-29 05:36:59 字數 2533 閱讀 7676

1.虛擬位址空間

程序位址空間需要隔離,防止惡意的程式修改其它程式的記憶體資料,因此計算機中引入虛擬位址空間。

虛擬位址空間布局

.text(**段)

可執行**、唯讀變數、字串常量

.data(資料段)

已初始化且初值非0的全域性變數和靜態變數(全域性和區域性)

.bss

未初始化或初始值為0的全域性變數和靜態變數。如果變數都已初始化,則bss段被清零

heap(堆)

動態申請的記憶體

共享庫程式執行時被動態載入到記憶體中使用(linux下為.so檔案,widow下為.dll檔案)

stack(棧)

程式執行時需要在這裡做資料運算,儲存臨時資料(區域性變數、區域性唯讀變數、函式引數、返回位址等),開闢函式棧等。linux下,棧是高位址往低位址開闢的。對於函式棧來說,函式執行完畢就釋放記憶體。

命令列引數

類似ps -elf 中-elf就是命令列引數,而ps是可執行程式。

環境變數

linux下的path,home等的環境變數(子程序會繼承父程序的環境變數)

zone_dma

直接訪問區,16m

zone_normal

常用區,對映頁目錄表,892m

高階記憶體區

大於1g的檔案的對映

2.編譯鏈結原理1)預編譯(生成*.i檔案)

1>將所有的「#define」刪除,並且展開所有巨集;

2>處理掉所有條件預編譯指令,如:「#if」、「#ifdef」、「#elif」、「#else」、「#endif」;

3>處理「#include」指令,這是乙個遞迴過程;

4>刪除所有的注釋「//」和「/* */」;

5>新增行號和檔名標識;

6>保留所有的#pragma編譯器指令,待編譯器使用;

2)編譯(生成*.s檔案)

把預處理完的檔案進行一系列的詞法分析,語法分析,語義分析及優化後生成相對應的彙編**檔案。

3)彙編(生成*.o檔案,也叫目標檔案)

彙編器是將彙編**轉變成機器可以執行的指令,每乙個彙編語句幾乎都對應一條機器指令。

.o檔案簡單的檔案格式布局

.bss不占用目標檔案的空間

可以看到elf header中有乙個叫做section headers的段,這個段儲存了目標檔案中每個段的詳細資訊,包括段的大小,起始偏移等等資訊。編譯器只要訪問這個段就可以知道每個段的詳細資訊。.bss雖然不佔空間但是.bss段的詳細資訊都被儲存在section headers中.

可以看到gdata3並不是存放在.bss段。這個資料存在com這個塊中,這個和c語言中的強弱符號有關

強符號:全域性的已初始化的符號 弱符號:全域性的未初始化的符號 強弱符號的選取規則:

1.兩個強符號 編譯報錯

2.乙個強符號 乙個弱符號 選擇強符號

3.兩個弱符號 根據不同編譯器處理方式不同

乙個專案可能有多個原始檔。編譯階段都是每個檔案單獨編譯的。可能在其他檔案中存在強符號,所以沒辦法在編譯期間確定具體的符號。因此將本檔案的弱符號存放在com塊,而不是.bss段。

符號解析和符號重定位

符號解析

在每個檔案符號引用(引用外部符號)的地方找到符號的定義。這就是符號解析

符號重定位

先看下鏈結前生成的彙編**

這兩處分別是 0000 0000代表鏈結前編譯器給gdata給出的位址,ff ff ff fc表示鏈結前編譯器給sum函式給出的函式的入口位址。這兩個位址都是無效的位址。再看看鏈結後這兩條位址

這兩個位址變成gdata的具體虛擬位址和sum函式的相對位移偏移量。而符號重定向就是對.o檔案中.text段指令中的無效位址給出具體的虛擬位址或者相對位移偏移量。

我們來看看可執行檔案的頭部資訊

可以看到這個時候這個程式的入口位址已經給定080480a4這個就是main函式的入口位址。現在程式就可以執行了。

編譯鏈結執行原理 虛擬位址空間布局

1 早期記憶體分配機制 在早期的計算機中,要執行乙個程式,會把這些程式全都裝入記憶體,程式都是直接執行在記憶體上的,也就是說程式中訪問的記憶體位址都是實際的物理記憶體位址。當計算機同時執行多個程式時,必須保證這些程式用到的記憶體總量要小於計算機實際物理記憶體的大小。但是同時存在以下3個問題 1 程序...

c 編譯鏈結執行原理及虛擬位址空間布局

當我們寫好.c cpp檔案時 此時檔案還不能執行 因為他要經過以下的四步才可以執行 c cpp 生成.i 編譯 生成.s 彙編 生成.o 鏈結 生成.exe 1.define巨集替換 1.詞法分析 指令翻譯成二進位制 1.合併段和符號表 2.include 遞迴展開 2.語法分析 2.符號解析 3....

程式編譯鏈結,執行原理,虛擬位址空間布局

1 預編譯過程 i 1.刪除 define文字替換 2.if endif elif 3.include遞迴展開 4.刪除注釋 5.新增行號 主要目的是為了方便除錯 6.保留 pragma 2 編譯 s 1.詞法分析 例 int 8a 10 變數不能以數字開頭 2.語法分析 根據一條表示式分析 3.語...