std::cout segmentation fault


今天測試功能,發現一個奇怪的問題,std::cout導致崩潰。調用過程如下圖:

gdb調試coredump文件,堆棧信息如下圖:

 定位具體崩潰日志,發現std::basic_ostream對象沒有初始化,如圖

 通過谷歌查資料,發現有一個報錯跟我類似,根據答復,發現問題出在ios_base::Init沒有初始化,

 

 

ios_base::Init用於構造此成員類型的對象,確保標准流對象(cin,cout,cerr,clog,cin,cout,cerr和clog)被構造和正確初始化。
根據答復,只需要include <iostream>便可以保證ios_base::Init初始化
在C++03中,std::ios_base::Init是未指定的,我們需要確保在輸入main()時,標准流已初始化。
C++11修復這個問題,#include <iostream>的每個實例都跟着static std::ios_base::Init __unspecified_name__,這樣可以自動保證流可以使用。
我檢查程序,發現程序中已經#include <iostream>,應該不存在ios_base::Init沒有初始化這種情況
懷疑是dlopen的操作機制影響了ios_base::Init的初始化

函數定義 void * dlopen(const char* pathName, int mode);
pathName 指的是db文件或listDB.so文件在實機環境中的位置, mode指的是打開數據庫的模式
mode在linux下,按功能有以下幾種
解析方式
RTLD_LAZY:
    暫緩決定,在dlopen返回前,對於動態庫中的未定義的符號不執行解析,只對函數引用有效,對於變量引用總是立即解析。這種模式有一個優勢,
例如動態庫中的某些函數引用了其他第三方庫,有些沒有,那么調用沒有引用第三方庫的函數時,可以不用把第三方庫的文件放在LD_LIBRARY_PATH下面 RTLD_NOW: 立即決定,在dlopen返回前,解析出所有未定義的符號,如果解析不出來,在dlopen會返回NULL,錯誤為 undefined symbol:XXX... 作用范圍 RTLD_GLOBAL: 動態庫中定義的符號可被其后打開的其他庫重定位 RTLD_LOCAL: 與RTLD_GLOBAL作用相反,動態庫中定義的符號不能被其后打開的其他庫重定位。如果沒有指明是RTLD_GLOBAL還是RTLD_LOCAL,那么默認是RTLD_LOCAL。 作用方式 RTLD_NODELETE:在dlclose()期間不卸載庫,並且在以后使用dlopen()重新加載庫時不初始化庫中的靜態變量。這個flag不是POSIX
-2001標准。 RTLD_NOLOAD: 不加載庫,可用於測試庫是否已經加載(dlopen()返回NULL說明未加載,否則說明加載),也可用於改變已加載庫的flag,
如:先前加載庫的flag為RTLD_LOCAL,用dlopen(RTLD_NOLOAD
|RTLD_GLOBAL)后flag將變成RTLD_GLOBAL.這個flag不是POSIX-2001標准 RTLD_DEEPBIND:在搜索全局符號前先搜索庫內的符號,避免同名符號的沖突,這個flag不是POSIX-2001標准

當dlopen中使用RTLD_DEEPBIND特性,可能會屏蔽全局std::ios_base::Init變量,導致iostream對象沒有初始化,

經過實驗,在dlopen中取消RTLD_DEEPBIND,崩潰問題得到解決。

 


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM