我正在基于 Linux 的作業系統上開發基于 Qt 的專案。我們使用 Qt5.9.6。當我們啟動我們的應用程式時,我們從 Qt 獲得了這個日志
qt.network.ssl: Incompatible version of OpenSSL
經過一些研究,我發現 Qt 加載了 1.1 版本的 openssl 而 Qt5.9.6 需要 1.0.2k 版本。因此,我將正確版本的 openssl 放在我們的應用程式旁邊,并相應地設定了 RPATH。但它不起作用。我會嘗試,LD_LIBRARY_PATH
并且有效。
我曾經LD_DEBUG=libs
看到程式嘗試加載動態庫的位置,似乎對于 Qt,RPATH 部分使用或根本不使用。
我創建了一個eaglejoe/qtopenssl-bug
以最小示例命名的 docker 映像。編譯示例啟動
cmake --preset default
cmake --build build
并啟動程式build/testqt
有人知道為什么 RPATH 在這里沒有完全使用嗎?
(在示例中使用的是 RUNPATH,但我對 RPATH 也有同樣的問題)
謝謝您的幫助
uj5u.com熱心網友回復:
所以問題是,Qt 將 OpenSSL 庫作為插件加載,ld.so
Linux 上的動態聯結器只考慮呼叫dlopen()
. 而且因為 Qt 本身沒有 OpenSSL 副本集的 rpath,所以它不會加載它。
最好的解決方法是(只要您不想使用該 rpath 自己重新編譯 Qt)在呼叫任何 Qt 函式之前手動加載 OpenSSL。因此,在代碼的開頭添加以下內容main()
:
void* crypto_handle = dlopen("libcrypto.so", RTLD_NOW | RTLD_GLOBAL);
if (!crypto_handle)
std::cerr << "error loading libcrypto.so: " << dlerror() << std::endl;
void* ssl_handle = dlopen("libssl.so", RTLD_NOW | RTLD_GLOBAL);
if (!ssl_handle)
std::cerr << "error loading libssl.so: " << dlerror() << std::endl;
請注意,您必須libcrypto.so
在 before加載libssl.so
,否則libssl.so
不會加載,因為libssl.so
在您的安裝中沒有為自己設定 rpath,因此libcypto.so
除非您自己也加載它,否則它不會找到正確的。
進一步說明:從技術上講,您可以使用官方 SONAMElibssl.so.1.0.0
和libcrypto.so.1.0.0
(是的,即使對于 1.0.2,這些都是正確的 SONAME),但是您的 Qt 版本是針對一個奇怪的 OpenSSL 版本編譯的,該版本認為它的 SONAME1.0.2k
作為擴展名,而不是1.0.0
它應該是,所以它只會通過它們的通用名稱找到庫,并且您必須通過它們的通用名稱(libssl.so
, libcrypto.so
)加載庫,以使動態聯結器知道這些是別名。
如果這兩個都被加載,Qt 將能夠作業,因為動態聯結器將看到相關庫已經加載到程式中,因此將重用它們,而不是在檔案系統中查找它們。
運行您的程式將給出以下輸出:
build openssl: OpenSSL 1.0.2k-fips 26 Jan 2017
load openssl: OpenSSL 1.0.2k 26 Jan 2017
話雖如此:OpenSSL 1.0.2 已經 2.5 年不支持了。而且您使用的版本1.0.2k
甚至更舊,那是 5.5 年前 (!) 以前的。從那以后,OpenSSL 中已經修復了幾個安全問題,當涉及到網路通信時,撰寫依賴于這些過時軟體的新代碼是一個非常糟糕的主意。
拜托,請使用 OpenSSL 1.1,它仍然支持到明年 9 月。Qt 從 5.12 開始支持。根據我的經驗,從 5.9 升級到 5.12 完全沒有痛苦。雖然理想情況下我建議新代碼應該使用 Qt6。
(不幸的是,甚至 Qt6 似乎還不能與 OpenSSL 3.0 一起使用,但希望這會很快改變。)
轉載請註明出處,本文鏈接:https://www.uj5u.com/qiye/496976.html
上一篇:在qt或qml中搜索字串突出顯示
下一篇:Qtimer事件未執行