C++靜態(tài)鏈接與動(dòng)態(tài)鏈接詳解
一、GCC工作流程
預(yù)處理:把#頭文件展開,進(jìn)行宏替換,去掉注釋(生成.i文件)
編譯:把預(yù)處理后的文件生成匯編文件(.s文件),主要是檢查語法、語義問題
匯編:把匯編文件生成目標(biāo)文件(.o文件)
鏈接:將函數(shù)庫中相應(yīng)的代碼組合到目標(biāo)文件,生成可執(zhí)行文件(默認(rèn)a.out文件)
o文件不會(huì)立即執(zhí)行,因?yàn)榭赡艹霈F(xiàn):一個(gè).cpp文件中的函數(shù)引用了另一個(gè).cpp文件中定義的符號(hào)/調(diào)用了某個(gè)庫文件中的函數(shù)。鏈接的目的就是將這些文件對(duì)應(yīng)的目標(biāo)文件鏈接成一個(gè)整體,從而生成可執(zhí)行文件。
二、靜態(tài)鏈接與動(dòng)態(tài)鏈接
程序庫:包含數(shù)據(jù)和執(zhí)行代碼的文件,不能單獨(dú)執(zhí)行,可以作為程序庫的一部分來完成某些功能。
庫的存在可以使程序模塊化,可以加快程序的再編譯,實(shí)現(xiàn)代碼復(fù)用,便于更新程序
程序庫又分為靜態(tài)鏈接庫與動(dòng)態(tài)鏈接庫
1、靜態(tài)鏈接
在鏈接階段,將匯編生成的.o文件和所需要的庫一起鏈接打包到可執(zhí)行文件中去,程序運(yùn)行的時(shí)候不再調(diào)用其它的庫文件
一個(gè)靜態(tài)庫,可以看作是一些目標(biāo)代碼的集合,在可執(zhí)行程序運(yùn)行前就已經(jīng)加入到執(zhí)行代碼中,成為執(zhí)行程序的一部分。
靜態(tài)鏈接的優(yōu)點(diǎn):對(duì)運(yùn)行環(huán)境依賴小,具有較好的兼容性。
靜態(tài)鏈接的缺點(diǎn):生成的程序較大,需要更多的系統(tǒng)資源(所需的所有庫都被打包進(jìn)可執(zhí)行文件了),在裝入內(nèi)存中消耗更多時(shí)間
一旦庫函數(shù)有了更新,必須重新編譯應(yīng)用程序
此處,我們制作實(shí)現(xiàn)加減乘除的靜態(tài)庫,首先編寫add.c、sub.c、mul.c、div.c文件及對(duì)應(yīng).h文件,另外編寫text.c文件進(jìn)行測(cè)試。gcc -c 生成目標(biāo)文件.o,然后將.o文件打包,制作靜態(tài)庫libtext.a
2、動(dòng)態(tài)鏈接
靜態(tài)庫存在的問題:
(1)若兩個(gè).o文件都使用同一個(gè)靜態(tài)庫,那么內(nèi)存中會(huì)拷貝2份靜態(tài)庫的代碼,然 后分別與兩個(gè).o文件一起打包到可執(zhí)行文件中,造成空間浪費(fèi)。
舉個(gè)例子:某個(gè)靜態(tài)庫占1M內(nèi)存,有2000個(gè).o文件使用這個(gè)靜態(tài)庫,內(nèi)存中有2000個(gè)靜態(tài)庫的代碼(將近2000GB),空間浪費(fèi)嚴(yán)重。
(2) 所需的庫被拷貝到可執(zhí)行文件中去了,如果某個(gè)庫更新了,則與它相關(guān)的所有可執(zhí)行文件都需要重新編譯。
為了解決這兩個(gè)問題,引出動(dòng)態(tài)庫(又稱共享庫),動(dòng)態(tài)庫在程序編譯時(shí),并不會(huì)被鏈接到目標(biāo)代碼中,而是在運(yùn)行時(shí)載入,不同應(yīng)用程序如果調(diào)用相同的的庫,內(nèi)存里只有一份共享庫的實(shí)例,避免了浪費(fèi)。由于動(dòng)態(tài)庫在運(yùn)行時(shí)才被載入,也解決了靜態(tài)庫對(duì)程序的更新、部署和發(fā)布帶來的馬糞,用戶只需要更新動(dòng)態(tài)庫即可。
動(dòng)態(tài)鏈接的優(yōu)點(diǎn):鏈接時(shí),僅僅建立與所需庫函數(shù)之間的關(guān)系;
在程序運(yùn)行時(shí)才將所需資源調(diào)入可執(zhí)行程序;
簡(jiǎn)化程序的升級(jí),有較小的程序體積;
實(shí)現(xiàn)進(jìn)程之間的資源共享,內(nèi)存中只有一份動(dòng)態(tài)庫的實(shí)例,避免充分拷貝
動(dòng)態(tài)鏈接的缺點(diǎn):依賴動(dòng)態(tài)庫,不能獨(dú)立運(yùn)行
動(dòng)態(tài)庫依賴版本問題嚴(yán)重
同樣的,我們制作制作實(shí)現(xiàn)加減乘除的動(dòng)態(tài)庫。
我們把動(dòng)態(tài)庫.so和測(cè)試文件.c拷貝當(dāng)前目錄,使得系統(tǒng)加載可執(zhí)行文件時(shí),能夠知道所依賴的庫的名字,但是還需要找到動(dòng)態(tài)庫的絕對(duì)路徑,此時(shí)需要系統(tǒng)動(dòng)態(tài)載入器(dynamic linker/loader)。對(duì)于elf格式的可執(zhí)行程序,是由ld-linux.so*來完成的。搜索elf文件的DT_PATH段(環(huán)境變量)LD_LIBRARY_PATH,/etc/ld.so.cache文件列表,/urs/lib目錄找到庫文件后將其載入內(nèi)存。
動(dòng)態(tài)庫加載失敗的解決辦法:這里給出兩個(gè)解決辦法,來找到動(dòng)態(tài)庫
總結(jié)
本篇文章就到這里了,希望能夠給你帶來幫助,也希望您能夠多多關(guān)注腳本之家的更多內(nèi)容!
- C++靜態(tài)變量,常量的存儲(chǔ)位置你真的了解嗎
- VisualStudio2019構(gòu)建C/C++靜態(tài)庫和動(dòng)態(tài)庫dll的問題 附源碼
- 關(guān)于C++靜態(tài)數(shù)據(jù)成員的實(shí)現(xiàn)講解
- 用Visual Studio2017寫C++靜態(tài)庫圖文詳解
- C/C++靜態(tài)類和this指針詳解及實(shí)例代碼
- C++靜態(tài)成員變量和靜態(tài)成員函數(shù)的使用方法總結(jié)
- 解決在Mac下直接解壓C++靜態(tài)庫出現(xiàn)的問題
- C++靜態(tài)持續(xù)變量介紹
相關(guān)文章
C++實(shí)現(xiàn)猜數(shù)小游戲的實(shí)現(xiàn)
這篇文章主要介紹了C++實(shí)現(xiàn)猜數(shù)小游戲的實(shí)現(xiàn),文中通過示例代碼介紹的非常詳細(xì),對(duì)大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價(jià)值,需要的朋友們下面隨著小編來一起學(xué)習(xí)學(xué)習(xí)吧2020-02-02VC中實(shí)現(xiàn)GB2312、BIG5、Unicode編碼轉(zhuǎn)換的方法
這篇文章主要介紹了VC中實(shí)現(xiàn)GB2312、BIG5、Unicode編碼轉(zhuǎn)換的方法,該功能非常實(shí)用,需要的朋友可以參考下2014-07-07一文詳解matlab實(shí)現(xiàn)形態(tài)學(xué)圖像處理
這篇文章主要為大家介紹了matlab實(shí)現(xiàn)形態(tài)學(xué)圖像處理詳解,有需要的朋友可以借鑒參考下,希望能夠有所幫助,祝大家多多進(jìn)步,早日升職加薪2023-03-03C++實(shí)現(xiàn)班級(jí)成績(jī)管理系統(tǒng)
這篇文章主要為大家詳細(xì)介紹了C++實(shí)現(xiàn)班級(jí)成績(jī)管理系統(tǒng),文中示例代碼介紹的非常詳細(xì),具有一定的參考價(jià)值,感興趣的小伙伴們可以參考一下2022-02-02Java?C++題解leetcode1598文件夾操作日志搜集器
這篇文章主要為大家介紹了Java?C++題解leetcode1598文件夾操作日志搜集器示例詳解,有需要的朋友可以借鑒參考下,希望能夠有所幫助,祝大家多多進(jìn)步,早日升職加薪2022-09-09VsCode安裝和配置c/c++環(huán)境小白教程(圖文)
本文主要介紹了VsCode安裝和配置c/c++環(huán)境小白教程,文中通過示例代碼介紹的非常詳細(xì),具有一定的參考價(jià)值,感興趣的小伙伴們可以參考一下2022-01-01