2011-10-12 57 views
6

作爲庫開發人員,我想阻止我的庫用戶(Windows,MSVC)鏈接到錯誤的配置(而不是將調試庫鏈接到他們的發佈程序,反之亦然)。防止混合調試和發佈庫

是否有可能在編譯期間警告用戶(s)他應鏈接到正確的庫配置?

編輯

Debug和Release版本應可讓Windows開發人員調試他們的應用程序。因此,我的庫的調試版本和發行版本都應該可用。

我在問這個問題,因爲很多對Windows初學者開發人員的支持是由於他們混合了調試和發佈代碼,以及難以調試的運行時錯誤。

+0

爲什麼你想讓你的客戶調試你的庫?你是否提供源代碼?設計您的API,以便編譯器設置無關緊要。 COM ABI就是一個很好的例子。 –

+0

如果你創建一個靜態庫而不是一個DLL,你必須以任何方式添加調試版本。否則,沒有人能夠創建調試版本。 – Totonga

回答

0

您可以添加#warning指令,但我強烈建議您不要這樣做。 您應該更好地以兩種不同的名稱提供給您的圖書館的不同版本。

這裏是你的問題的另一種暗示:

myLib.h // Release Version 
myLibd.h // Debug Version 

做它喜歡的是,這將迫使用戶照顧時,他們將建立您的圖書館中的應用(因爲設置必須手動) 。

您也可以在自述文件或INSTALL中添加註釋,大多數用戶在想要設置MSVC上的鏈接時閱讀它。

您還可以檢查程序中的DEBUG和NDEBUG宏值。 (在你的庫初始化期間聲明)

4

好問題,我一直認爲使用我的庫的開發人員會鏈接到正確的版本,現在我想到了,爲什麼你甚至想要發佈你的調試庫?公衆爲何不應同時他們的調試和發佈版本對你的版本庫無論鏈接

,我看到這樣的方式通過出口每個配置一些符號:

//header: 
class DLLIMPEXP Dummy 
{ 
    static int x; 
    virtual void dummy(); 
} 
//cpp 
#ifdef DEBUG 
int Dummy::x = 0; 
void Dummy::dummy() 
{ 
} 
#endif 

,你可以請參閱,如果您的模塊在DEBUG中編譯,則只會導出您的符號。嘗試鏈接到發行版m中的lib來自第三個模塊的代碼會導致鏈接器錯誤。對於相反的情況,你可以有類似的東西。

我不建議你這樣做,但我寧願將其記錄下來,或者只發布我的模塊的發佈版本。

+0

非常有趣。你有一個想法:添加將在庫中的非內聯函數IsReleaseVersion()。並添加構造函數內聯檢查(將包含在應用程序端)以檢查其版本。 – Phong

+0

我剛剛編輯了這個問題來回答你的一些問題。 僅當用戶嘗試在自己的代碼中使用該符號時,纔會觸發鏈接錯誤。此外,我希望用戶得到一個明確的信息,告訴他們「你沒有鏈接到正確的圖書館」。 – Mourad

+0

@Mourad:您可以將缺少的符號命名爲PleaseUseReleaseVersionOfXxxLibrary,同樣請PleaseUseDebugVersionOfXxxLibrary。 –

1

這裏有兩個不同的方面:

  • 不兼容的問題
  • 性能問題

如果它的性能問題,則選擇仍然應該是他們的,他們可能希望調試。

如果這是一個不兼容的問題,那麼一件簡單的事情就是更改調試版本的名稱空間,以便符號的修改方式不同。

#ifdef NDEBUG 
    namespace project { 
#else 
    namespace project { namespace debug { 
#endif 

// content 

#ifdef NDEBUG 
    } 
#else 
    } 
    using namespace debug; 
    } 
#endif 

通過在debug命名空間嵌套,你改變的符號是混淆(儘管,編譯明智的,它不會改變任何東西)。這實際上阻止鏈接一個針對調試版本與發佈版本編譯的庫(並因此儘早解決了不兼容問題而不是神祕地崩潰)。

但是,我會敦促你保留這個到一個非常特定的類(它很重)。

通常應該可以在調試和發佈模式下提供兼容接口,以便客戶端可以在加載時進行熱插拔。

0

將此代碼添加到您的LIB的頭

不同的名稱不同類型

#ifndef _DLL 
// C runtime as dll 
# ifdef _DEBUG 
# pragma comment(lib, "MyLibD.lib") 
# else 
# pragma comment(lib, "MyLib.lib") 
# endif 
#else 
// C runtime statically 
# ifdef _DEBUG 
# pragma comment(lib, "MyLibSD.lib") 
# else 
# pragma comment(lib, "MyLibS.lib") 
# endif 
#endif 

針對不同類型的

#ifndef _DLL 
// C runtime as dll 
# ifdef _DEBUG 
# pragma comment(lib, "debug/dynamic/MyLib.lib") 
# else 
# pragma comment(lib, "release/dynamic/MyLib.lib") 
# endif 
#else 
// C runtime statically 
# ifdef _DEBUG 
# pragma comment(lib, "debug/static/MyLib.lib") 
# else 
# pragma comment(lib, "debug/static/MyLib.lib") 
# endif 
#endif 

不同的路徑之後,你只需要將lib的路徑添加到鏈接器,並且不再是ab把它混合起來。

+1

這通常不被認爲是好的做法(在代碼中指定庫),但它是一個解決方案,所以我不會downvote 。 –

+0

如果你開發一個靜態庫而不是一個DLL,我總是會提供這個。有很多優點和避免錯誤,我不會關心哲學原因。 – Totonga