C語言中連接器介紹

       在C語言中,一個重要的思想就是分別編譯,即若干個源程序可以在不同的時候單獨進行編譯,然後在恰當的時候整合到一起。但是連接器一般是與C編譯器分離的,連接器如何做到把若干個C源程序合併成一個整體呢?

       典型的連接器把由編譯器或彙編器生成的若干個目標模塊,整合成一個被稱爲載入模塊或可執行文件的實體,該實體能夠被操作系統直接執行。其中,某些目標模塊是直接作爲輸入提供給連接器的;而另外一些目標模塊則是根據連接過程的需要,從包括有類似printf函數的庫文件中取得的。

       連接器通常把目標模塊看成是由一組外部對象組成的。每個外部對象代表着機器內存中的某個部分,並通過一個外部名稱來識別。因此,程序中的每個函數和每個外部變量,如果沒有被聲明爲static,就都是一個外部對象。某些C編譯器會對靜態函數和靜態變量的名稱做一定改變,將它們也作爲外部對象。由於經過了“名稱修飾”,所以它們不會與其他源程序文件中的同名函數或同名變量發生命名衝突。

       大多數連接器都禁止同一個載入模塊中的兩個不同外部對象擁有相同的名稱。然而,在多個目標模塊整合成一個載入模塊時,這些目標模塊可能就包含了同名的外部對象。連接器的一個重要工作就是處理這類命名衝突。

       處理命名衝突的最簡單辦法就是乾脆完全禁止。對於外部對象是函數的情形,這種做法是正確的。一個程序如果包括兩個同名的不同函數,編譯器根本就不應該接受。而對於外部對象是變量的情形,問題就變得困難了。不同的連接器對這種情形有着不同的處理方式。

       現在講講連接器是如何工作的?

       連接器的輸入是一組目標模塊和庫文件。連接器的輸出是一個載入模塊。連接器讀入目標模塊和庫文件,同時生成載入模塊。對每個目標模塊中的每個外部對象,連接器都要檢查載入模塊,看是否已有同名的外部對象。如果沒有,連接器就將該外部對象添加到載入模塊中;如果有,連接器就要開始處理命名衝突。

       除了外部對象之外,目標模塊還可能包括了對其他模塊中的外部對象的引用。例如:一個調用了函數printf的C程序所生成的目標模塊,就包括了一個對函數printf的引用。可以推測得出,該引用指向的是一個位於某個庫文件中的外部對象。在連接器生成載入模塊的過程中,它必須同時記錄這些外部對象的引用。當連接器讀入一個目標模塊時,它必須解析出這個目標模塊中定義的所有外部對象的引用,並作出標記說明這些外部對象不再是未定義的。

發佈了36 篇原創文章 · 獲贊 15 · 訪問量 22萬+
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章