由一次 symbol lookup error 引發的思考


開發一個跨平台的項目的時候,大部分時候都是在VS下進行編碼,所以也就使用了VS的解決方案來管理項目。
因為要跨平台,當時網上看scons這個工具不錯,所以在linux下就使用了scons來作為編譯腳本。

linux(gcc)下與windows(vs)下的對於鏈接這一步稍有不同。當目標文件是一個(共享)庫的時候,VS會在鏈接的時候就去解析所有用到的符號,而gcc則不會,只有在生成最終可執行程序的時候才會去解析。
所以在VS下,一直都沒有問題。linux下進行測試的時候也沒有問題(因為不是所有的代碼都被調用了)。

這幾天在一次移植過程中出現了如下的問題

/a.out: symbol lookup error: ./uds_file_storage_module.so: undefined symbol: _ZN8unispace13us_ini_config9from_fileERKNS_10us_ustringEPS0_

錯誤很簡單,就是us_ini_config::from_file這個函數沒有找到,說明沒有將其添加到動態導出符號表中。(uds_file_storage_module.so是運行時動態加載的,所以編譯的時候沒有提示錯誤)

VC中導出符號需要使用到dllexport,而gcc下則默認是不需要。所以這個問題很是疑惑。

考慮用的gcc版本比較高,是不是它將-fvisibility的參數默認設置為hidden呢?查看了gnu的wiki之后也沒有發現這個。

https://gcc.gnu.org/wiki/Visibility

這里還是有收獲的,看到一段好的跨平台代碼。

#if defined _WIN32 || defined __CYGWIN__
  #ifdef BUILDING_DLL
    #ifdef __GNUC__
      #define DLL_PUBLIC __attribute__ ((dllexport))
    #else
      #define DLL_PUBLIC __declspec(dllexport) // 注記:實際上gcc似乎也支持這種語法。
    #endif
  #else
    #ifdef __GNUC__
      #define DLL_PUBLIC __attribute__ ((dllimport))
    #else
      #define DLL_PUBLIC __declspec(dllimport) // 注記:實際上gcc似乎也支持這種語法。
    #endif
  #endif
  #define DLL_LOCAL
#else
  #if __GNUC__ >= 4
    #define DLL_PUBLIC __attribute__ ((visibility ("default")))
    #define DLL_LOCAL  __attribute__ ((visibility ("hidden")))
  #else
    #define DLL_PUBLIC
    #define DLL_LOCAL
  #endif
#endif

extern "C" DLL_PUBLIC void function(int a);
class DLL_PUBLIC SomeClass
{
   int c;
   DLL_LOCAL void privateMethod();  // Only for use within this DSO
public:
   Person(int _c) : c(_c) { }
   static void foo(int a);
};

然后添加了__attribute__((visibility("default")))進行修飾,發現編譯的結果沒有改變(md5sun判斷)。

然后又在鏈接的時候添加-rdynamic參數,將所有符號都添加到動態符號表,編譯結果也沒有變。

在仔細查看了SConstruct腳本之后,發現問題在於沒有將對應的源文件添加到腳本中。也就是編譯的時候完全就沒有編譯us_ini_config::from_file所在的源文件。
這樣問題就很清晰明了了,修改腳本之后重新編譯就可以了。


說到這里,就該反思一下了。
這個項目早期確實是直接寫的Makefile來進行編譯的,使用SOURCES = $(shell find $(SRC_DIR)$(PROJECT)/ -name "*.cpp")來自動發現cpp文件,這本來是很好的。對於貿然使用自己不熟悉的scons,又沒有進行有效的學習,這是很不好的。
對於這個項目,還是直接使用qmake來做跨平台的編譯腳本比較好。


免責聲明!

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



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