連結的目的連結過程

來源:互聯網
上載者:User

1.  連結的目的

    原始碼經過編譯後,產生了一系列的目標檔案。每一個目標檔案,具有自己的程式碼片段、資料區段、符號表、重定位表等資訊(參考目標檔案結構介紹)。

    在程式碼片段中,編譯產生的機器代碼需要訪問資料區段的資料,或是程式碼片段的函數。但在單個目標檔案中,只有局部的資料和代碼資訊。如下例:

    檔案a.c:

    unsigned long a = 10;

     

    void main()

    {

        print_a();

    }

 

    檔案b.c:

    #include <stdio.h>

    extern unsigned long a;

    void print_a()

    {

        printf(“%d”,a);

    }

    編譯後,a.c和b.c分別產生了a.o和b.o檔案。在a.o中,資料區段中為a,程式碼片段中有main;在b.o中,程式碼片段中有print_a函數。

    a.o中,訪問了b.o中的print_a函數,而b.o中訪問了a.o中的資料a。但問題是每一個.o都只能知道自已的局部資料和函數的地址,因此就需要通過連結過程,對a.o和b.o中的指令(調用print_a函數及訪問a資料)進行重點位。這也是靜態連結的主要目的所在。

 

    2. 
連結的過程

    連結主要分為兩個步驟以:

    1) 
空間與地址分配

       
每個.o檔案中都有自己的程式碼片段和資料區段,在多個檔案合并後,這些指令和資料如何組織?通常是採用相似段合并的方式,將多個.o檔案中的程式碼片段合并為一個程式碼片段,資料區段合并為一個資料區段。

       
這樣做的好處是可以空間消耗(因為作業系統在分配空間時最小單位是頁),並且可以提高記憶體訪問的命中率。

       
在進行相似段合并時,連結器會根據.o中每個段的長度、屬性和位置等,計算出合并後的長度與位置,然後並每一個.o的中的符號合并到全域符號表,記錄每一個符號的新的位置。

 

    2) 
符號解析與重定位

       
這一步是連結過程中核心,連結器通過重定位表,擷取到每一個需要進行重定位的指令的位置以及符號,然後通過符號表查詢符號的地址,修改指令中訪問的地址。

       
如果在這個過程中,無法在符號表中找到需要重定位的符號,就會出現連結失敗,也就是我們常見的”undefined reference to ‘xxx’”錯誤。

 

       
在符號表中,除了全域符號外,COMMON類型的符號也需要進行重定位,又稱為COMMON塊。COMMON塊通常用來處理弱符號。

       
編譯器將未初始化的全域變數定義為弱符號。當多個原始碼檔案中存在相同的弱符號時,連結器採用如下策略決定弱符號的大小:

       
(1)    存在同名的強符號時,以強符號為準

       
(2)    不存在同名強符號時,以最大的弱符號為準

 

聯繫我們

該頁面正文內容均來源於網絡整理,並不代表阿里雲官方的觀點,該頁面所提到的產品和服務也與阿里云無關,如果該頁面內容對您造成了困擾,歡迎寫郵件給我們,收到郵件我們將在5個工作日內處理。

如果您發現本社區中有涉嫌抄襲的內容,歡迎發送郵件至: info-contact@alibabacloud.com 進行舉報並提供相關證據,工作人員會在 5 個工作天內聯絡您,一經查實,本站將立刻刪除涉嫌侵權內容。

A Free Trial That Lets You Build Big!

Start building with 50+ products and up to 12 months usage for Elastic Compute Service

  • Sales Support

    1 on 1 presale consultation

  • After-Sales Support

    24/7 Technical Support 6 Free Tickets per Quarter Faster Response

  • Alibaba Cloud offers highly flexible support services tailored to meet your exact needs.