解析引用過程
在符號解析階段,鏈結器從左到右按照它們在編譯器驅動程式命令列上的出現順序來掃瞄可重定位目標檔案和存到檔案。
在這次掃瞄中,鏈結器維護乙個可重定位目標檔案的集合e(這個集合中的檔案就是確定的最後合併成可執行檔案的模組檔案),
乙個未解析的符合(即引用了但尚未定義的符號)集合u,以及乙個已解析(前面已經定義但沒有被引用)集合d。
對於命令列上的每個檔案 f ,鏈結器會判斷 f 是乙個目標檔案還是存檔檔案。
1.判斷輸入檔案型別
如果是目標檔案
如果是存檔檔案
鏈結器將嘗試匹配集合u中未解析的符號和存檔檔案成員定義的符號,如果存檔檔案的成員m定義了乙個符號來解析u中的乙個引用,
那麼久將m加入到集合e中,然後修改u和d的狀態。對存檔檔案中的每個成員都重複這個過程,直到u和d不再發生變化,然後簡單地丟棄
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,並不會像存檔檔案一樣遍歷。
鏈結器符號解析演算法小解以及靜態庫鏈結順序等等問題
在編寫linux驅動程式時,時常會發現鏈結出錯,當時往往不知道錯誤在哪。現在了解到鏈結器的工作原理之後,明白當時為什麼出錯了。對於以後有效率地編寫驅動程式有很大幫助。乙個c語言程式,經過諸如gcc之類的編譯器編譯成可執行檔案一般會經歷4個處理過程,這個大部分的linux入門書籍都有講到過,如果沒有扔...
鏈結器符號解析演算法小解以及靜態庫鏈結順序等等問題
一 編譯鏈結 在編寫linux驅動程式時,時常會發現鏈結出錯,當時往往不知道錯誤在哪。現在了解到鏈結器的工作原理之後,明白當時為什麼出錯了。對於以後有效率地編寫驅動程式有很大幫助。乙個c語言程式,經過諸如gcc之類的編譯器編譯成可執行檔案一般會經歷4個處理過程,這個大部分的linux入門書籍都有講到...
學習筆記 如何使用靜態鏈結庫
程式設計環境 vs2017 第一步 建立靜態庫工程,工程名稱為 staticlib003 第二步 增加標頭檔案int.h pragma once define crt secure no warnings include include include include extern c int ad...