防止混合调试和发布库

时间:2011-10-12 08:59:12

标签: c++ visual-c++

作为一名图书馆开发人员,我想阻止我的图书馆用户(Windows,MSVC)链接到错误的配置(不将调试库链接到他们的发布程序,反之亦然)。

是否可以在编译期间警告用户他应该链接到库的正确配置?

修改

调试版和发布版都应该可用,以允许Windows开发人员调试他们的应用程序。所以我的库的调试和发布版本都应该可用。

我问这个问题,因为很多对Windows初学者开发人员的支持是由于他们混合了调试和发布代码,以及难以调试的运行时错误。

4 个答案:

答案 0 :(得分:4)

好问题,我一直认为使用我的库的开发人员会链接到正确的版本。现在我考虑一下,为什么你甚至想要向公众发布你的调试库?为什么他们的调试版本和发布版本都不能链接到您的发布库?

无论如何,我通过在每个配置中导出一些符号来看到这样做的方法:

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

如您所见,只有在DEBUG中编译模块时才会导出符号。尝试从发布模式链接到第三个模块的lib将导致链接器错误。对于相反的情况,你可以有类似的东西。

我不建议你这样做,我宁愿记录它或只发布我的模块的发布版本。

答案 1 :(得分:1)

这里有两个不同的方面:

  • 不兼容问题
  • 效果问题

如果是性能问题,那么选择应该仍然是他们的,他们可能希望调试。

如果这是一个不兼容的问题,一个简单的事情是更改调试版本的命名空间,以便符号被不同地修改。

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

// content

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

通过嵌套在debug命名空间中,可以更改符号的重整(即使编译方面,它也不会更改任何内容)。这实际上阻止将根据调试版本编译的库与发布版本链接(从而在早期解决了不兼容问题,而不是神秘地崩溃)。

但是,我建议你把它保留到一组非常具体的课程中(这很重)。

通常,应该可以在调试和释放模式下提供兼容的接口,以便客户端可以在加载时进行热交换。

答案 2 :(得分:0)

您可以添加#warning指令,但我强烈建议您不要这样做。 您应该使用两个不同的名称更好地传送到不同版本的库。

以下是您的问题的另一个提示:

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

这样做会强制用户在用库设置应用程序时要小心(因为设置必须是手动的)。

您还可以在README或INSTALL中添加注释,大多数用户在想要在MSVC上设置链接时读取它。

您还可以在程序中检查DEBUG和NDEBUG宏值。 (在库初始化期间使用断言。

答案 3 :(得分: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的路径添加到你的链接器,你就不能再把它混淆了。