1. 程式人生 > >Linux系統的動態庫和靜態庫

Linux系統的動態庫和靜態庫

靜態庫

靜態庫:一些公共程式碼是需要反覆使用,就把這些程式碼編譯為“庫”檔案;在連結步驟中,聯結器將從庫檔案取得所需的程式碼,複製到生成的可執行檔案中的這種庫。

程式編譯一般需經預處理、編譯、彙編和連結幾個步驟。靜態庫特點是可執行檔案中包含了庫程式碼的一份完整拷貝;缺點就是被多次使用就會有多份冗餘拷貝。

生成靜態庫

靜態庫生成:將所有的***.o 檔案打包在一起生成

打包的命令:ar -cr lib***.a ***.o (其中-c建立,-r模組替換)

1、編輯c++檔案、和對應的標頭檔案,標頭檔案不可省略,標頭檔案用於告知使用者如何使用該動態庫。

C++檔案

//test.cc
#include "test.hpp"

int Add(int a,int b)
{
    return a+b;
}

標頭檔案test.hpp,這個標頭檔案是必須要有的,在呼叫靜態庫的源程式中要引該標頭檔案,用來告訴源程式,靜態庫的函式實現。

#include <iostream>

int Add(int a,int b);

2、生成.o檔案

g++ -c test.cc -o test.o

3、生成靜態庫

ar -cr libtest.a test.o

4、檢視靜態庫是否成功生成

objdump -S libtest.a				//檢視靜態庫內容

在這裡插入圖片描述

5、使用靜態庫

編輯了一個C++檔案

//main.cc
#include <iostream>
#include "test.hpp"		//這裡必須包含靜態庫的標頭檔案

int main()
{
    int a = 10,b = 20;
    std::cout << Add(a,b) << std::endl;
    return 0;
}

-L靜態庫路徑 靜態庫名稱

在這裡插入圖片描述

動態庫

動態庫又稱動態連結庫,動態連結提供了一種方法,使程序可以呼叫不屬於其可執行程式碼的函式。

動態庫:一份動態庫可以被用到該庫的所有程序共用,外部函式的機器碼由作業系統從磁碟上覆制到記憶體(虛擬記憶體的共享區)中的過程叫做動態連結。

在這裡插入圖片描述

一個動態連結的可執行程式檔案僅僅包含它用到的函式的入口地址的一個表,而不是外部函式所在目標檔案的整個機器碼。

生成動態庫(執行時庫)

1、 --share是生成動態庫的gcc連結選項,沒有這個,將認為生成可執行程式
將所有的.o檔案打包 生成命令:gcc --share ***.o -o lib***.so
2、要生成一個動態庫,gcc編譯器說:在編一階段,將一個.c——>.o需要加上一個編譯選項:-fPIC(產生位置無關程式碼)。動態庫當中的程式碼不能是絕對地址,只能是相對地址,因此需要-fPIC,產生與位置無關的程式碼。
gcc -fPIC -c  ***.c -o  ***.o        
g++ -fPIC -c test.cc -o test.o
g++ --share  test.o -o libtest.so
3、檢視動態庫內容:
objdump -S libtest.so

在這裡插入圖片描述

4、gcc 的連結屬性:-Lpath用於指定庫的查詢路徑,-lname用於指定連結的庫名稱(去掉字首和字尾)

如果出現以下錯誤,那麼說明,你的動態庫沒有放到指定的動態庫路徑下,它執行時候,找不到動態庫,才報錯。

./a.out: error while loading shared libraries: libtest.so:
 cannot open shared object file: No such file or directory

在這裡插入圖片描述
但作為一個簡單的測試例子,讓我們改動系統的東西,似乎不太合適。還有另一種簡單的方法,就是為a.out指定 LD_LIBRARY_PATH。

LD_LIBRARY_PATH=. ./a.out

程式就能正常運行了。LD_LIBRARY_PATH=. 是告訴 a.out,先在當前路徑尋找連結的動態庫。
在這裡插入圖片描述

靜態庫和動態庫是兩種共享程式程式碼的方式,它們的區別是:靜態庫在程式的連結階段被複制到了程式中,和程式執行的時候沒有關係;動態庫在連結階段沒有被複制到程式中,而是程式在執行時由系統動態載入到記憶體中供程式呼叫。使用動態庫的優點是系統只需載入一次動態庫,不同的程式可以得到記憶體中相同的動態庫的副本,因此節省了很多記憶體。