1. 程式人生 > 其它 >靜態庫和動態庫

靜態庫和動態庫

靜態庫:
1. 編譯時連結;
2.浪費空間和資源,如果多個程式連結了同一個庫,則每個生成的可執行檔案就都會有一個庫的副本,必然浪費系統的空間;
3.若靜態庫修改了,需要重新進行編譯所有連結的程式

動態庫:
1. 執行時連結
2. 執行時被連結,程式執行速度稍慢
3.動態庫在程式執行時被連結,所以磁碟上只需要保留一份副本,因此節約磁碟空間。如果發現bug或者升級也很簡單,只需要用新的庫把原來的替換掉。

GCC編譯流程:
1.預處理:C/C++原始檔中,#開頭的命令都是預處理命令,包括標頭檔案,巨集定義以及條件編譯等。預處理就是將標頭檔案插入到原始檔中,把巨集定義展開,根據條件編譯選擇使用程式碼,最後這些程式碼輸出到.i檔案等待下一步處理。
gcc -E hello.c -o hello.i
2.編譯:將C/C++程式碼編譯成彙編程式碼
gcc -S hello.i -o hello.s
3.彙編:將編譯等到的檔案翻譯成一定格式的機器程式碼
gcc -c hello.s -o hello.o
4.連結:將上步生成的OBJ檔案和系統的OBJ檔案,庫檔案連結起來,生成可執行檔案。
gcc hello.o
靜態連結是在GCC編譯中連結時一起打包到可執行檔案;而動態庫在程式編譯時並不會連結導目的碼中,而是在程式執行時才載入。不同的應用程式如果呼叫相同的庫,那麼在記憶體中只需要有一份該共享庫的例項,規避了浪費空間的問題。動態庫是在程式執行時才載入,也解決了靜態庫對程式的更新,部署和釋出帶來的麻煩。使用者只需要更新動態庫即可。

生成靜態庫:
ar crv libfoo.a foo.c other.c
載入靜態庫:
g++ -o main main.cpp -L. -lfoo -static

生成動態庫:
g++ -o libshare.so -fPIC -shared share1.cpp share2.cpp
載入動態庫:
g++ -o main mian.cpp -L. -lshare
通過g++來指定路徑:
g++ -o main main.cpp -Wl,-rpath=./ -L. -lshare
-Wl,-rpath是用來指定動態庫的路徑

此外,動態庫指定路徑有以下幾種方法:
1.export更改LD_LIBRARY_PATH當前終端的環境變數
2.cp libfoo.so /usr/lib //將庫拷貝到系統庫路徑下

(不推薦)
3修改/etc/ld.so.conf檔案,加入庫檔案所在目錄的路徑,然後 執行ldconfig 目錄名字,該命令會重建/etc/ld.so.cache檔案即可
4.gcc指定路徑