解析引用過程
在符號解析階段,鏈接器從左到右按照它們在編譯器驅動程序命令行上的出現順序來掃描可重定位目標文件和存到文件。
在這次掃描中,鏈接器維護一個可重定位目標文件的集合E(這個集合中的文件就是確定的最后合並成可執行文件的模塊文件),
一個未解析的符合(即引用了但尚未定義的符號)集合U,以及一個已解析(前面已經定義但沒有被引用)集合D。
對於命令行上的每個文件 f ,鏈接器會判斷 f 是一個目標文件還是存檔文件。
1.判斷輸入文件類型
如果是目標文件
鏈接器將會把這個文件添加到集合E,並根據符號引用情況修改集合U和D的狀態。然后處理下一個文件。
如果是存檔文件
鏈接器將嘗試匹配集合U中未解析的符號和存檔文件成員定義的符號,如果存檔文件的成員m定義了一個符號來解析U中的一個引用,
那么久將m加入到集合E中,然后修改U和D的狀態。對存檔文件中的每個成員都重復這個過程,直到U和D不再發生變化,然后簡單地丟棄
不包含在集合E中的成員目標文件。然后鏈接器繼續處理下一個文件。
2.判斷集合U是否為空
如果鏈接器掃描完命令行上的所以文件后,集合U仍不為空,則說明引用了未定義的符號,則鏈接器將會報錯並終止程序。
如果鏈接器掃描完命令行上的所以文件后,集合U仍為空,則將合並和重定位E中的目標文件,並輸出可執行文件。
注意命令行上的庫和目標文件的順序
一般將庫放在命令行的結尾
1.如果庫之間是相互獨立的,則可以以任意的順序放在命令行的結尾處。
2.如果庫之間是相互依賴的關系,則必須對他們排序,使得對於每個被存檔文件的成員外部引用的符號s,在命令行中至少有一個s的定義是在對s的引用之后的。
例如,a和b表示當前目錄中的目標模塊或者靜態庫,而a->b表示a依賴於b,也就是說b定義了一個被a引用的符號。
p.o->libx.a->liby.a且liby.a->libx.a->p.o
可得最小命令行 gcc p.o libx.a liby.a libx.a
注意不要寫成 gcc p.o libx.a liby.a libx.a p.o //要注意區分存檔文件和目標文件,目標文件將整個添加到E,並不會像存檔文件一樣遍歷。