最近有幸閱讀了《高階c/c++編譯技術》深受啟發,該書深入淺出地講解了構建過程(編譯、鏈結)中的各種細節,從多個角度展示了程式與庫檔案或**的整合方法,提出了面向**復用和系統整合的軟體架構設計方法,以及系統開發過程中疑難問題的解決方案。以下將回頭記錄下其中的關鍵要點,以便後面查閱。
首先,需要理解載入域與執行域的概念。載入域是**存放的位址,執行域是**執行時的位址。為什麼會產生這2個概念?這2個概念的實質意義又是什麼呢?
在一些場合,一些**並不在儲存這部分**的位址上執行位址,比如說,放在norflash中的**可能最終是放在ram中執行,那麼中norflash中的位址就是載入域,而在ram中的位址就是執行域。
在彙編**中我們常常會看到一些跳轉指令,比如說b、bl等,這些指令後面是乙個相對位址而不是絕對位址,比如說b main,這個指令應該怎麼理解呢?main這裡究竟是乙個什麼東西呢?這時候就需要涉及到鏈結位址的概念了,鏈結位址實際上就是鏈結器對**中的變數名、函式名等東西進行乙個位址的編排,賦予這些抽象的東西乙個位址,然後在程式中訪問這些變數名、函式名就是在訪問一些位址。一般所說的鏈結位址都是指鏈結這些**的起始位址,**必須放在這個位址開始的地方才可以正常執行,否則的話當**去訪問、執行某個變數名、函式名對應位址上的**時就會找不到,接著程式無疑就是跑飛。但是上面說的那個b main的情形有點特殊,b、bl等跳轉指令並不是乙個絕對跳轉指令,而是乙個相對跳轉指令,什麼意思呢?就是說,這個main標籤最後得到的只並不是main被鏈結器編排後的絕對位址,而是main的絕對位址減去當前的這個指令的絕對位址所得到的值,也就是說b、bl訪問到的是乙個相對位址,不是絕對位址,因此,包括這個語句和main在內的**段無論是否放在它的執行域這段**都能正常執行。這就是所謂的位置無關**。
由上面的論述可以得知,如果你的這段**需要實現位置無關,那麼你就不能使用絕對定址指令,否則的話就是位置有關了。
靜態庫是通過編譯器編譯源**檔案並將生成的目標檔案打包生成後的歸檔檔案,我們通過名為歸檔器(archiver)的工具來生成靜態庫
$ gcc -c first.c second.c
$ ar rcs libstaticlib.a first.o second.o
ar工具還可以完成以下任務:
(1)從庫檔案中刪除乙個或多個目標檔案
(2)從庫檔案中替換乙個或多個目標檔案
(3)從庫檔案中提取乙個或多個目標檔案
鏈結器將靜態庫的節拼接到客戶二進位制檔案,當鏈結完成後,靜態庫的節將與客戶二進位制檔案中的原有的目標檔案節進行無縫鏈結,靜態庫中的符號成為客戶二進位制檔案符號列表中的一部分,並且保留了其原有的可見性,靜態庫中的全域性符號成為客戶二進位制檔案的全域性符號,同樣地,靜態庫的區域性符號也稱為客戶二進位制檔案的區域性符號。
但是,當客戶二進位制檔案是乙個動態庫時,上面的原則還是不是一樣呢?
動態庫的設計原則規定只提供(即介面可見性)滿足與外部通訊的介面,採用該設計原則最終會影響到靜態庫符號的可見性,靜態庫的符號不會作為全域性可見的符號保留,而是會變成私有符號或被忽略(即動態庫的符號表中沒有這個靜態庫符號)
(1)當鏈結乙個靜態庫需要多個動態庫時,可能不應該使用靜態庫,選擇使用動態庫可能會比較有利
(2)應該使用同一庫的已存在的動態庫版本
(3)如果你所實現的功能需要存在乙個類的單個示例中,最好使用動態庫
在linux下鏈結靜態庫需要遵循下列規則
(1)依次鏈結靜態庫,每次乙個靜態庫
(2)鏈結靜態庫從傳遞給聯結器的靜態庫列表的最後乙個靜態庫開始(通過命令或者makefile),且會反方向逐個鏈結,直到列表中的第乙個位置
(3)鏈結器會對靜態庫進行詳細的檢索,在所有的目標檔案中,只有包含客戶二進位制檔案實際所需符號的目標檔案才會進行鏈結
由於這些特定的規則,我們有時需要在傳遞給鏈結器的靜態列表多次新增同乙個靜態庫,當乙個靜態庫同時提供了多種完全不同的功能時,就會遇到這種多次新增的情況
(1)使用打包工具(ar)來提取所有靜態庫中的目標檔案
$ ar -x .a
執行該命令會把靜態庫中的目標檔案集合提取到當前目錄
(2)鏈結器使用提取出來的目標檔案集合來構建動態庫
在64位linux平台上使用靜態庫會遇到乙個非常特殊的情況
(1)將靜態庫鏈結到可執行檔案與在32位linux上進行操作沒有任何區別
(2)但是,靜態庫鏈結到共享庫則要求靜態庫需要用-fpic或-mcmodel-large編譯器選項來進行構建(編譯器在編譯過程中的錯誤列印輸出時的建議)
靜態庫的匯入選擇條件:當客戶端二進位制檔案鏈結靜態庫時不會把整個靜態庫的內容鏈結進來,智慧型鏈結目標檔案中必要的符號動態庫的匯入選擇條件:當客戶端二進位制檔案鏈結動態庫時,選擇的條件是在符號表這個層面上,只會選擇包含在符號表中實際需要的動態庫符號,但是在其它所有方面,這個選擇條件實際上是不存在的,無論動態庫功能中具體需要的**有多少都會將整個動態庫鏈結進來。
高階C C 編譯技術之讀書筆記(一)之編譯 鏈結
最近有幸閱讀了 高階c c 編譯技術 深受啟發,該書深入淺出地講解了構建過程 編譯 鏈結 中的各種細節,從多個角度展示了程式與庫檔案或 的整合方法,提出了面向 復用和系統整合的軟體架構設計方法,以及系統開發過程中疑難問題的解決方案。以下將回頭記錄下其中的關鍵要點,以便後面查閱。1 節 供cpu執行的...
高階C C 編譯技術之讀書筆記(四)之定位庫檔案
最近有幸閱讀了 高階c c 編譯技術 深受啟發,該書深入淺出地講解了構建過程 編譯 鏈結 中的各種細節,從多個角度展示了程式與庫檔案或 的整合方法,提出了面向 復用和系統整合的軟體架構設計方法,以及系統開發過程中疑難問題的解決方案。以下將回頭記錄下其中的關鍵要點,以便後面查閱。1 靜態庫 lib a...
數學之美讀書筆記(二)
chapter.6資訊的度量和作用 1.一條資訊的資訊量就等於其不確定性 熵 越是不確定的事物越是要大量資訊去說明 以位元為衡量單位 資訊是消除不確定性的唯一方法 2.幾乎所有自然語言處理,資訊與訊號處理的應用都是乙個消除不確定性的過程 3.合理利用資訊,而不是玩弄什麼公式和機器學習演算法,是做好搜...