System-Installation
共享庫次要版本管理
我有一個簡單的程序叫做
main
:#include <iostream> #include "random.h" int main() { std::cout << "The program has started\n"; return get_another_random_number(); }
該
get_another_random_number()
函式在新版本的共享庫中,但只安裝了舊版本。程序開始執行,但稍後在查找失敗時崩潰;例如$ ./main The program has started ./main: symbol lookup error: ./main: undefined symbol: _Z25get_another_random_numberv
例如,如果
librandom.so.1.3.1
包含一個名為 的函式get_another_random_number()
,但main
在僅librandom.so.1.2.5
安裝的伺服器上執行,則會發生這種情況。這些庫僅在其次要版本上有所不同,因為該1.3
版本與庫的版本向後兼容1.2
,但1.2
缺少額外的功能。在我自己的範例中,如果我執行,
readelf -d main | grep NEEDED
我會得到:0x0000000000000001 (NEEDED) Shared library: [librandom.so.1] 0x0000000000000001 (NEEDED) Shared library: [libstdc++.so.6] 0x0000000000000001 (NEEDED) Shared library: [libm.so.6] 0x0000000000000001 (NEEDED) Shared library: [libgcc_s.so.1] 0x0000000000000001 (NEEDED) Shared library: [libc.so.6]
因此,所有內容都僅與主要版本號相關聯。
對於我的共享庫,我將其放入
/usr/lib/
並添加了符號連結:lrwxrwxrwx 1 root root 23 Feb 7 14:25 /usr/lib/librandom.so -> /usr/lib/librandom.so.1 lrwxrwxrwx 1 root root 27 Feb 7 14:13 /usr/lib/librandom.so.1 -> /usr/lib/librandom.so.1.2.5 -rw-r--r-- 1 root root 7696 Feb 7 14:00 /usr/lib/librandom.so.1.2.5
在庫維護者、應用程序開發者和系統管理員之間;誰負責避免這個程序崩潰?
- 是不是在安裝過程
main
中應該產生一個錯誤,指出目前安裝的庫的次要版本太低?- 程序是否應該呼叫庫中的特殊函式來辨識版本並檢查次要版本是否足夠?
- 庫載入器是否應該在程序開始執行之前檢查所有符號?
- 我是否誤解了版本編號或錯過了檢查次要版本的設置?
您沒有誤解版本編號,這確實是通常需要進行符號查找的領域。
至於這是誰的責任,我想說的是,在現代系統上,它屬於建構應用程序的人,而不是庫:如果您將應用程序連結到
ld -z now
(至少在 GNU binutils 上),動態連結器將在啟動時解析所有符號如果缺少任何符號,則提前失敗(因此您無需添加自己的手動檢查)。您可以在程序連結後通過導出LD_BIND_NOW=1
到環境來啟用此行為(任何非空值都有效,這不是 Linux 特定的)。這類問題通常由包管理系統處理:它們保留描述符號版本要求的大量元數據,並生成適當的版本依賴項。圖書館作者也可以幫助改善這種情況,但這可能需要付出很多努力;查看 GNU libc 的特殊版本符號(
GLIBC_...
經常出現在錯誤消息中的符號)以及對版本符號的一般徹底處理。