測試給我提了一個BUG,咱們的程序在鏈接HTTPS服務端後,莫名crash。
在還原測試環境後,經過gdb調試,發現crash在libcurl的curl_easy_platform這個函數裏面,因而開啓了漫長的debug之旅,最終發現是函數符號衝突所致。curl
靜態庫libA.a 動態庫libB.so 可執行二進制test.bin
靜態庫A主要導出一個函數接口TestFunc
主要代碼:函數
extern "C" void TestFunc(std::string const& strData) { std::cout<<"This is libtestA"<<std::endl; std::cout<<strData<<std::endl; }
動態庫B導出兩個函數接口,一個TestFunc,另外一個函數調用靜態庫A的TestFunc 主要代碼:測試
extern "C" __attribute__((visibility("default"))) void TestFunc(std::string const& strData) void TestFunc(std::string const& strData) { std::cout<<"This is libtestB"<<std::endl; std::cout<<strData<<std::endl; } extern "C" __attribute__((visibility("default"))) void TestFunc_Ex() { //寫一個測試類,經過類裏面Test函數調用靜態庫A的TestFunc函數 TestClass _t; _t.Test(); }
test.bin調用動態庫B裏面的兩個函數接口
主要代碼:編碼
int main() { TestFunc("hoho"); TestFunc_Ex(); return 0; }
This is libtestB hoho This is libtestB TestClass::Test
若是將靜態庫A導出的函數的參數修改成空,那麼從新編譯後,再運行test.bin,就復現了crash。url
This is libtestB hoho This is libtestB Segmentation fault (core dumped)
理想中的結果應該是:.net
This is libtestB hoho This is libtestA TestClass::Test
出現這個問題的緣由是:
在Linux下,全部同名函數,都會被第一個加載的函數符號所代替,因此test.bin調用的時候,所有都走了動態庫B的TestFunc函數。debug
遇到這種函數符號衝突的問題,編譯器一般不會給你任何提示。出現crash,只能經過gdb和經驗來一步一步排查。
解決方法能夠經過編譯傳參數來指定導出函數來解決,但我不建議這種方法。在大型項目中添加多餘的編譯參數及文件是一種很挫的作法。我仍是建議在編碼中注意規範,多檢查、多用命名空間來約束、避免這類問題。調試
示例代碼Demo下載地址code