定位windows客戶端鏈接問題

最近需要在客戶端添加一個定時查詢功能,能夠在客戶端登錄時查詢股票的中籤信息。
需要去查詢中籤並在中籤時,彈窗提示用戶。
最初的想法是定義一個全局靜態變量,然後再全局變量初始化的時候,去創建qt的定時器。在定時器超時時觸發查詢操作。
此種實現能通過編譯,但是在運行的時候會報錯,因爲全局變量的初始化在c++中比較早,遠早於qt的動態庫加載時機,所以一運行就失敗。
 
然後採用第二種方法,創建一個單例模式,在main函數之後調用創建單例的操作,進而創建qt定時器,然後再觸發查詢操作。
採用這種方法結果發現在鏈接時出現鏈接錯誤LNK2019。然後在 https://learn.microsoft.com/ 查找原因。
結果試了裏面所有的方法,都沒有解決問題,但我心想這肯定不是一個技術上的大問題,估計是配置之類的蛋疼問題;因爲別人都正常開發,要出現重大的技術問題,早出現了。
下面就就詳細闡述一下,這個花費我2天時間才解決的問題。
因爲window和linux不一樣,每一個dll會使用一個地址空間,而linux上是所有的文件使用一個共同的地址空間,這也導致linux開發更爲容易,
因爲window畢竟是大型商業的操作系統,用戶各種各樣,它的設計就更復雜。
所以當程序分爲多個模塊(動態庫)時,一個模塊要使用另外一個模塊的代碼(或稱爲符號)時,就需要在一個模塊裏面導出,然後另外一個模塊才能找到此符號鏈接。
導出的方式通常有使用代碼宏,def文件,exp文件(用於靜態庫lib文件)。
我們工程裏面採用代碼宏,通過在編譯不同模塊時,根據編譯選項,在不同的代碼模塊宏的展開是不同的,其中在一個模塊展開爲導出,在另外一個模塊展開爲導入。
如下代碼:
#ifndef BUILD_STATIC
# if defined(XXXX_LIB)
# define XXXX_EXPORT Q_DECL_EXPORT
# else # define XXXX_EXPORT Q_DECL_IMPORT
# endif
#else
# define XXXX_EXPORT
#endif
 
 
# define Q_DECL_EXPORT __declspec(dllexport)
# define Q_DECL_IMPORT __declspec(dllimport)
在一個模塊中XXXX_EXPORT因爲宏XXXX_LIB被展開爲__declspec(dllexport),另外一個模塊展開爲__declspec(dllimport); 在vs編譯器模塊編譯時要配置編譯宏XXXX_LIB
 
在檢測了代碼的編譯宏,也沒有發現任何問題。
然後懷疑導入的符號表,沒有真正導出,後面使用vs自帶的工具DUMPBIN,導出庫的所有符號,發現也導出來了。
用vs自帶的UNDNAME將導出的符號逆轉爲函數,也完全正確。
 
然後看到網上說可能是因爲編碼的方式不對,然後使用下面的宏也不行,還是鏈接時找不到符號。
#pragma execution character set("utf-8")
基本上把微軟官方的錯誤情況都試過了,還是解決不了。
最後只好問了維護這套代碼的人,讓我把編譯出來的庫,在工程裏面替換所有舊的庫。
然後就連着正常。
 
這個問題完全是一個工程配置問題,但這套被太多的人維護,一個庫會被人拷了多個備份,而編譯的時候只會覆蓋一個地方,而鏈接時又用到其他地方的同名文件。
 
這個問題使用了windows的工具鏈,還是對自己有點積極意義。
在windows下面DUMPBIN類似於linux的nm命令,UNDNAME類似於linux的c++fileter;
下面粘貼上windows的LNK2019鏈接
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章