1. 程式人生 > >C++靜態庫和動態庫

C++靜態庫和動態庫

靜態庫與動態庫

首先簡單介紹一下gcc 指令

ubuntu 下安裝gcc g++ 方法

sudo apt install gcc g++

gcc 的簡單使用

建立hello.c 原始檔
gcc hello.c => 生成a.out
gcc hello.c -o hello => 生成hello
./a.out | ./hello 執行

編譯步驟

  1. 預處理 生成.i 檔案
  2. 編譯 生成.s 檔案
  3. 生成目標檔案 .o
  4. 連結各個.o 檔案生成可執行檔案

gcc常用引數選項

gcc編譯選項 選項的意義
-E 預處理指定的原始檔,不進行編譯
-S 編譯指定的原始檔,不進行彙編
-c 編譯、彙編指定的原始檔,不進行連結
-o 指定生成檔名字
-I directory 指定 include 包含檔案的搜尋目錄
-g 編譯時,生成除錯資訊,該程式可以被偵錯程式除錯
-D 在程式編譯的時候,指定一個巨集 如開啟DEBUG -D DEBUG
-w 不生成任何警告資訊
-Wall 生成所有警告資訊
-O [123] n的取值範圍:0~3。編譯器的優化選項的4個級別,-O0表示沒有優化,-O1為預設值,-O3優化級別最高
-l 在程式編譯的時候,指定使用的庫
-L 指定編譯的時候,搜尋的庫的路徑。
-fPIC/fpic 生成與位置無關的程式碼
-shared 生成共享目標檔案。通常用在建立共享庫時
-std 指定編譯標準 如-std=c++1z或-std=gnu++17或-std=c++17

靜態庫

  • Linux 靜態庫
    • libxxx.a
      • lib 字首
      • xxx 庫的名字
      • .a 字尾
  • Windows 靜態庫
    • libxxx.lib

靜態庫的製作

  1. 生成 .o 檔案

    gcc xxx.c xxx.c xxx.c -c

  2. 使用ar 打包
    1. ar rcs
    2. -r 替換
    3. -c 建立
    4. -s 索引

    ar rcs libxxx.a xxx.o xxx.o xxx.o

靜態庫的使用

引入標頭檔案與需要的靜態庫libxxx.a (標頭檔案中聲明瞭靜態庫的介面,libxxx.a為介面的實現)
gcc main.c -o app -I ./include/ -L 靜態庫路徑 -l 靜態庫名字

  • -L 靜態庫路徑
  • -l 靜態庫名字 為libxxx.a 中的xxx

動態庫/共享庫

  • Linux 動態庫
    • libxxx.so
      • lib 字首
      • xxx 庫的名字
      • .so 字尾
  • Windows 動態庫
    • libxxx.dll

動態庫製作

  1. 生成 .o 檔案 (與位置無關)

    gcc -c xxx.c xxx.c xxx.c -c -fpic
    -fpic/-fPIC 使用相對地址記錄程式碼位置

  2. gcc -shared xxx.o xxx.o xxx.o -o libcxxx.so

動態庫使用

引入標頭檔案與需要的動態庫libxxx.so 標頭檔案中聲明瞭靜態庫的介面,libxxx.a為介面的實現)
$ gcc main.c -o app -I ./include/ -L 動態庫路徑 -l 動態庫名字

工作原理

  • 靜態庫在程式編譯時會連結到目的碼中,程式執行時不再需要靜態庫,體積較大。每次編譯都需要載入靜態程式碼,記憶體開銷大。
  • 動態庫在程式執行時才被載入,程式執行時需要動態庫存在,體積較小。系統只需載入一次動態庫,不同程式可以得到記憶體中相同的動態副本,記憶體開銷小。

解決動態庫找不到的問題:

第一種: 將動態庫的絕對路徑新增到 LD_LIBRARY_PATH 中

  1. 測試時候使用的, 終端關閉, 設定失效:
    在當前終端中執行: export LD_LIBRARY_PATH=$LD_LIBRARY_PATH:/庫的路徑
  2. 長久設定, 將export LD_LIBRARY_PATH=$LD_LIBRARY_PATH:/庫的路徑 寫到配置檔案中
  • 使用者: ~/.bashrc

新增: export LD_LIBRARY_PATH=$LD_LIBRARY_PATH:/庫的路徑

  • 系統: /etc/profile

新增: export LD_LIBRARY_PATH=$LD_LIBRARY_PATH:/庫的路徑

  • 新增完成執行命令, 使修改生效:

. ~/.bashrc
. /etc/profile
source /etc/profile
. 相當於 source

第二種: 在 /etc/ld.so.cache 新增動態庫路徑

  1. 開啟檔案: /etc/ld.so.conf
  2. 將.so檔案路徑的目錄新增到/etc/ld.so.conf, 更新: sudo ldconfig
  3. /etc/ld.so.conf的作用:記錄了程式載入執行期間查詢動態連結庫時的路徑。

靜態庫與動態庫的區別

靜態庫特點總結:

靜態庫對函式庫的連結是放在編譯時期完成的。
程式在執行時與函式庫再無瓜葛,移植方便。
浪費空間和資源,所有相關的目標檔案與牽涉到的函式庫被連結合成一個可執行檔案

動態態庫特點總結:

動態庫把對一些庫函式的連結載入推遲到程式執行的時期。
可以實現程序之間的資源共享。
程序升級變得簡單。(只修改需要升級部分,靜態庫則需要整個重新編譯)