靜態編譯與動態編譯的區別

2021-07-23 09:48:55 字數 4344 閱讀 2432

靜態編譯與動態編譯的區別

動態編譯的可執行檔案需要附帶乙個的動態鏈結庫,在執行時,需要呼叫其對應動態鏈結庫中的命令。所以其優點一方面是縮小了執行檔案本身的體積,另一方面是加快了編譯速度,節省了系統資源。缺點一是哪怕是很簡單的程式,只用到了鏈結庫中的一兩條命令,也需要附帶乙個相對龐大的鏈結庫;二是如果其他計算機上沒有安裝對應的執行庫,則用動態編譯的可執行檔案就不能執行。

靜態編譯就是編譯器在編譯可執行檔案的時候,將可執行檔案需要呼叫的對應動態鏈結庫(.so)中的部分提取出來,鏈結到可執行檔案中去,使可執行檔案在執行的時候不依賴於動態鏈結庫。所以其優缺點與動態編譯的可執行檔案正好互補。

用  靜態lib將匯出宣告和實現都放在lib中。編譯後所有**都嵌入到宿主程式

動態lib相當於乙個h檔案,是對實現部分(.dll檔案)的匯出部分的宣告。編譯後只是將匯出宣告部分編譯到宿主程式中,執行時候需要相應的dll檔案支援

lib檔案是不對外公開的,不能檢視乙個編譯過後的檔案

有幾個選擇:

1。如果你檢視有同名的dll檔案,可以通過vc自帶的depends檢視dll介面

2。通過msdn看你使用的該lib包含的函式名,來查詢其對應的標頭檔案,標頭檔案裡面有整個lib的函式宣告(可能不全)

3。檢視vc或者其他工具安裝目錄下的src目錄,檢視函式的**

lib檔案是二進位制檔案,所以要檢視它的內容,只能反彙編。

用程式語言,開啟lib檔案的辦法有三個:

1、在object/library modules使用全路徑名;

2、把*.lib放在vc的lib目錄中

3、修改project setting的link->input中的addtional library path,加入你的目錄。

lib檔案是庫檔案(與dll檔案相類似),供其它程式呼叫的,直接打不開。

編輯本段lib檔案操作

乙個lib檔案是obj檔案的集合。當然,其中還夾雜著其他一些輔助資訊,目的是為了讓編譯器能夠準確找到對應的obj檔案。我們可以通過tlib.exe(在tc2.0下的根目錄)來對lib檔案進行操作,你可以把自己生成的obj檔案通過tlib命令加入到乙個lib檔案中,也可以把lib檔案內的obj檔案進行刪除操作,還可以把內部的obj檔案給提取出來。明白了lib檔案的大致結構以及對它的具體操作,在學習c語言的過程中,就會又多了乙個切入點對c語言具體實現進行研究。

在command下,把當前目錄設定為tlib.exe所在目錄,然後輸入tlib命令回車,此時顯示的內容就是對tlib命令的詳細解釋,語法如下:

syntax: tlib libname [/c] [/e] commands, listfile

libname library file pathname

commands sequence of operations to be performed (optional)

listfile file name for listing file (optional)

a command is of the form: modulename, where is:

+ add modulename to the library

- remove modulename from the library

* extract modulename without removing it

-+ or +- replace modulename in library

-* or *- extract modulename and remove it

/c case-sensitive library

/e create extended dictionary

具體解釋:

tlib libname [/c] [/e] commands, listfile

/c:大小寫敏感標誌。該選項不常用,此引數為可選項。

/e:建立擴充套件字典。建立擴充套件字典可以加速大的庫檔案的連線過程,此引數同樣為可選項。

操作命令(可選項):

+ obj檔名 把指定obj檔案新增到lib檔案中

- obj檔名 把指定obj檔案從lib檔案中刪除

* obj檔名 匯出指定的obj檔案(匯出後對應的obj檔案在lib檔案內仍然存在)

-+ obj檔名 替換指定的obj檔案(前提是在lib檔案中存在與指定obj檔案同名的obj)

-* obj檔名 匯出指定的obj檔案(匯出後把對應的obj檔案從lib檔案內刪除)

lib檔案中obj檔案列表(可選項)

此引數說明了命令執行後,生成的對應lib檔案的列表檔名。它記錄了當前lib檔案內obj檔案列表

編輯本段lib檔案中的節

lib格式只有四種型別的節(section),即first sec,second sec,longname sec和obj sec;其中second sec與longname sec是可選節,很多lib檔案中都沒有。而開頭的singature只是乙個標識,它相當於coff目標檔案中的魔法數字。它是乙個長度為8的字串,值為「!\n」。

first sec 顧名思義,就是第乙個節。它包含了庫中所有的符號名以及這些符號所在的目標檔案在庫中的位置(絕對偏移)。

second sec 就是第二節。它的內容和first sec是相同的。不同的是,second sec是乙個有序表,通過它來查詢庫中的符號比通過first sec來查詢要快很多。

longname sec 是長名稱節。這一節是乙個字串表。它包含了所有長目標檔名。如果後面的obj sec中沒有給出相應的目標檔名,我們就要到這一節中來查詢。

obj sec 就是目標檔案節。這些節中儲存著不同的目標檔案的原始資料。

在庫檔案中,每一節都有兩個部分。乙個部分是頭,另乙個部分才是該節的資料;資料緊跟在頭的後面。頭描述了該節資料的型別、長度等資訊。這些頭的格式都是相同的。其結構用c語言描述如下:

typedef struct sectionheader;

可以看到,頭中的資料全都是字串。用字串的好處是可以提高格式的相容性,因為在不同的機器上,資料的排列方式是不同的。有的機器是以little-endian方式工作,還有的是以big-endian方式工作,它們互不相容(這兩種方式的區別!?請看我的《coff格式》一文,其中的檔案頭一節有說明)。用字串就不會有這種問題(後面我們將會遇到)。但它也有不方便的地方,就是必須把字串轉換成數值,多了乙個步驟。

在這個結構中,最常用的name、size以及endofheader三個成員。name就是節的名稱啦!size也很好理解,就是該節資料的長度。現在要注意的就是這個endofheader成員了!這個成員標誌著頭的結束,其內容為「\n」(注意,這裡沒有打錯,是兩個字元「」和「\n」)。怎麼樣?有點奇怪吧?為什麼要有這個結束符?每一節的頭長度一定,每節中的資料長度也知道。按順序向下讀不行嗎?答案是:不行!因為每一節之間存在間隙!通常是乙個位元組或零個位元組。如果是零個位元組倒好,按順序向下讀是ok的。可是如果不為零的話,這樣讀就要錯位了。要知道錯位沒有,只好用乙個結束符來定位了。如果在讀頭的時候發現結束符不對,那就要乙個位元組乙個位元組地向下查詢,直到找到結束符,才能算是對齊了。切記!切記!

當然,通過first sec或second sec中給出的偏移來讀資料就不存在這個問題。不會發生錯位,放心讀吧!

現在讓我們來看看每一節中的資料是什麼樣子。

first sec

第一節,通常就是lib中的每乙個小節。它的名稱是「/」。其資料部分的結構如下:

typedef struct firstsec;

第乙個成員symbolnum是符號的數量。注意!它是以big-endian方式儲存的(x86平台上的資料是以little-endian方式儲存的。這裡應該注意轉換。後面給出的convert函式可以在little-endian格式與big-endian格式之間進行相互轉換)。

第二個成員symboloffset是乙個陣列,它的長度n就是符號的數量,也就是symbolnum。這個陣列儲存了每乙個符號所在的目標節的偏移。我們可以方便地通過它來查詢符號所在的目標檔案。注意!它也是以big-endian格式儲存的。

第三個成員strtable是乙個字串表,它的長度m就是sectionheader.size的值減去(symbolnum+1)*4。其結構很簡單,就是一堆以『\0』結尾的字串(和coff檔案中的字串表結構相同)。在有的系統中,它還可能是以「/\n」這兩個字元結尾的字串的集合。

很簡單的乙個結構,不過有兩個成員的長度是不定的。怎麼才能方便地從lib中讀出這些資料,留給大家自己想吧!下面我只給出乙個進行little-endian與big-endian互轉的函式。

inline void convert(void * p // 要轉換的資料的指標

,size_tsize = 4 // 資料的長度,long為4,short為2

char * buf=(char*)p;

char temp;

for ( size_t i=0;i

靜態編譯與動態編譯的區別

靜態編譯與動態編譯的區別 動態鏈結庫 動態 有 靜態 無 動態編譯 動態編譯的可執行檔案 需要附帶乙個的動態鏈結庫 在執行時,需要呼叫其對應動態鏈結庫中的命令。優點 一方面是縮小了執行檔案本身的體積 一方面是加快了編譯速度,節省了系統資源。缺點 二是如果其他計算機上沒有安裝對應的執行庫,則用動態編譯...

apache動態編譯 靜態編譯區別

以前編譯apache的時候 都是google搜尋到的直接拿來用 這次自己編譯mod rewrite和ssl遇到了問題 又不知道問題出在 乙個是mod rewrite模組沒有起作用 乙個是以ssl啟動apache的時候報告如下錯誤 後來經過查詢 明白了問題出在 當時我是這麼編譯apache的 conf...

busybox動態編譯靜態編譯的區別

busy box選擇靜態編譯的話,命令和工具集不需要動態載入lib裡面的庫,所以在製作根檔案系統的時候就不需要往裡面新增庫檔案,省了這一步雖然方便,但是這樣的話,你做的根檔案系統就不能執行動態鏈結的程式了,因為你的開發板裡面沒有庫啊,為了能夠執行動態鏈結的程式,你把arm linux gcc裡面的庫...