核心區別:鏈接時機
| 特性 | 靜態庫 (.a/.lib) | 動態庫 (.so/.dll) |
| 鏈接階段 | 編譯時 (靜態鏈接) | 運行時 (動態鏈接) |
| 代碼副本 | 嵌入可執行文件 | 內存共享一份 |
| 可執行體積 | 較大 | 較小 |
| 部署更新 | 全量更新 | 增量更新 (替換 .so/.dll) |
| 依賴關系 | 無運行時依賴 | 需庫文件存在 |
| 符號解析 | 鏈接器完成 | 動態鏈接器完成 |
Linux 平台實戰
靜態庫
# 創建
g++ -c StaticMath.cpp -o StaticMath.o
ar -crv libstaticmath.a StaticMath.o
# 使用
g++ test.cpp -L. -lstaticmath -o test
./test
動態庫
# 創建 (-fPIC 位置無關代碼,-shared 生成共享庫)
g++ -fPIC -shared DynamicMath.cpp -o libdynmath.so
# 使用 (需庫在搜索路徑)
g++ test.cpp -L. -ldynmath -o test
# 運行時找不到庫解決:
# 1. cp libdynmath.so /usr/lib/
# 2. export LD_LIBRARY_PATH=.:$LD_LIBRARY_PATH
# 3. 編輯 /etc/ld.so.conf + ldconfig
Windows (MSVC) 平台實戰
靜態庫 (.lib)
- VS 項目屬性 → 配置類型 → 靜態庫 (.lib)
- 或命令行:
cl /c StaticMath.cpp → lib StaticMath.obj
動態庫 (.dll + .lib 導入庫)
- VS 項目屬性 → 配置類型 → 動態庫 (.dll)
- 導出函數需
__declspec(dllexport)
- 生成:
DynamicMath.dll (運行時代碼) + DynamicMath.lib (導入庫,僅符號表)
- 使用:鏈接
.lib,運行時載入 .dll
關鍵區別
StaticMath.lib 190 KB ← 實際代碼+符號表
DynamicMath.lib 3 KB ← 僅導入符號表 (地址存根)
DynamicMath.dll 100 KB ← 實際代碼
動態庫顯式調用 (運行時加載)
Linux: dlopen 族
#include
void* handle = dlopen("./libdynmath.so", RTLD_LAZY);
auto add = (double(*)(double,double))dlsym(handle, "_ZN10DynamicMath3addEdd"); // mangled name
add(1.0, 2.0);
dlclose(handle);
C++ name mangling 導致符號難以預測,建議 extern "C" 導出純 C 接口:
extern "C" double add_wrapper(double a, double b) { return DynamicMath::add(a,b); }
Windows: LoadLibrary 族
HMODULE h = LoadLibrary("DynamicMath.dll");
auto add = (double(*)(double,double))GetProcAddress(h, "add_wrapper");
add(1.0, 2.0);
FreeLibrary(h);
顯式調用 C++ 類的困境
- 無標準 API 實例化類 (需工廠函數導出)
- 跨 DLL 邊界傳遞 C++ 對象極其危險 (內存分配器、異常、STL 版本不匹配)
- 建議:能用隱式鏈接就不用顯式;必須顯式時,導出 C 接口封裝
常用工具命令
| 命令 | 用途 |
| nm libxxx.a | 查看符號表 (T=定義, U=未定義, W=弱符號) |
| ldd a.out | 查看動態依賴 |
| objdump -T libxxx.so | 查看動態符號表 |
| dumpbin /EXPORTS xxx.dll | Windows 查看導出函數 |
選型決策樹
是否需插件/熱更新/多進程共享? → 動態庫
是否嵌入式/無文件系統/極致性能? → 靜態庫
第三方庫是否僅提供動態版? → 動態庫
是否輕量工具/單文件分發? → 靜態庫
預設建議:動態庫 (現代系統內存豐富,共享收益大)
避坑指南
- 循環依賴:動態庫間循環依賴會導致載入失敗
- 符號衝突:多個動態庫導出同名符號,用
-Bsymbolic 或版本腳本
- ABI 兼容:動態庫升級保持接口兼容,否則需重新編譯依賴方
- Windows DLL Hell:應用程序目錄優先搜索,避免系統目錄版本衝突