【问题标题】:Mixing debug and release library/binary - bad practice?混合调试和发布库/二进制文件 - 不好的做法?
【发布时间】:2012-07-24 10:14:34
【问题描述】:

在调试二进制文件中使用 3rd 方库的发布版本是一种不好的做法吗?

我正在使用第 3 方库并编译了发布 .lib 库。我的 exe 处于调试模式开发。然后我得到了:

error LNK2038: mismatch detected for '_ITERATOR_DEBUG_LEVEL': value '0' doesn't match value '2' in test1.obj

经过一番谷歌搜索后,我发现这是因为我试图将发布与调试混合在一起,我可能应该在调试模式下编译库,否则会混淆 _ITERATOR_DEBUG_LEVEL 宏。但我只是好奇这是否是推荐的方式以及为什么。我需要为我打算使用的每个 3rd 方库编译并记录发布和调试二进制文件,这似乎很麻烦,这很快就会很多,同时无意调试这些代码。

【问题讨论】:

  • 您是否无法联系此第 3 方以获取调试版本或自己构建调试版本?
  • 这不仅仅是一种不好的做法:几乎可以保证程序要么崩溃要么做坏事。在 VS2010 之前,您无论如何都可以链接,以在运行时发现奇怪的错误。现在至少你被阻止了。
  • @JesseGood 是的,我有源代码,我刚刚编译了调试版本。问题解决了。我只是想知道我是否可以摆脱编译和跟踪一种模式。显然不是!
  • 它在 Windows 上,但它不应该。在调试模式下编译所有内容可能会导致总的程序速度和周转时间不可接受。考虑构建 webkit 引擎并在调试模式或某种解释器语言中使用它。但正如答案所说,在没有动态运行时 DLL 链接的情况下使用 DLL 时,您可能会侥幸成功
  • @AlexandreC。你确定VS2010?你说VS2010也失败了。但是现在我从 VS2010 转到 VS2019 第一次看到这个错误。

标签: c++ visual-studio-2010 visual-studio


【解决方案1】:

混合调试和发布代码是不好的做法。问题是不同的版本可能取决于 C++ 运行时库的不同基本部分,例如内存分配方式、迭代器等结构可能不同,可能会生成额外代码来执行操作(例如检查迭代器)。

这与混合使用任何其他不同设置构建的库文件相同。想象一个头文件包含应用程序和库都使用的结构的情况。该库是用结构打包和对齐设置为一个值构建的,而应用程序是用另一个值构建的。无法保证将结构从应用程序传递到库中会起作用,因为它们的大小和成员位置可能会有所不同。

是否可以将您的第 3 方库构建为 DLL?假设任何函数的接口都更干净并且不尝试传递任何 STL 对象,那么您将能够将调试应用程序与发布 DLL 混合使用而不会出现问题。

【讨论】:

  • 特别是 std 容器和迭代器是不同的和不兼容的。这就是您所看到的检查:它通过添加额外的字段来影响迭代器的布局。 std::string 的东西(仅)支持 Debug 和 Release 之间的兼容性,但 stl 中的其他任何东西都不起作用。
  • @JDługosz std::string 在运行时之间显式不兼容。一个有趣的练习是创建一个只有函数__declspec(dllexport) std::string make_string() 的DLL,在Debug 中构建,然后构建一个Release 可执行文件,链接并调用该函数。当我尝试std::cout 返回的字符串时,导致的崩溃非常剧烈。这是使用 VS2013,但这肯定是 VS2010 的问题,我希望其他版本也是如此。 Here's马口中的小信息。
  • 嗯,我研究的特定版本具有使调试和发布标准字符串(迭代器或值;不再记得了)互兼容的代码。我相信它比 VS2010 还要老,但我不记得它到底是多久以前了。
  • 虽然,在 Linux 上,当您使用包管理器时,您会获得仅用于优化配置 AFAIK 的库的预构建版本。只有 Windows 似乎有这种分离的 debug v 发布概念,这使得维护预构建的依赖关系成为一个巨大的痛苦。在 VS2010 之前,将发布(优化)库与调试可执行文件链接总是非常好的。 ABI 兼容性不应在配置之间改变。
  • @tinman 基于上一句的前提,我是否可以混合调试和发布代码?反过来,混合一个发布应用程序和调试DLL。传递STL对象如何影响。
【解决方案2】:

混合调试和发布库/二进制文件是一种很好且非常有用的做法。

调试大型解决方案(例如 100 多个项目)通常速度不快,甚至根本不可能(例如,并非所有项目都可以在调试中构建)。以前的评论员写道,调试/发布二进制文件可能有不同的对齐方式或其他人员。这不是真的。调试和发布二进制文件中的所有链接参数都是相同的,因为它们依赖于相同的体系结构。

您必须从所选项目中删除所有优化 (/Od)。然后分配一个发布 c++ 运行时。

出现问题是因为您在项目中定义了 _DEBUG。从定义中删除宏(项目->属性->预处理器->预处理器定义)。

如果宏不在预处理器定义中,则必须将其添加到“UndefinePreprocessorDefinitions”中。

【讨论】:

  • 我完全同意。这是常见的做法(至少在 linux 世界中)。你不想调试 3d 派对库,基本上我不能没有源。
  • 我一直选择非调试 CRT,但它不起作用。 _DEBUG 宏定义同样是罪魁祸首。感谢您提供此信息!
【解决方案3】:

它无法编译的事实足以证明这是一种不好的做法。

关于维护单独的构建 - 您不需要这样做。这是以前对我有用的解决方法:

#ifdef _DEBUG
#define DEBUG_WAS_DEFINED
#undef _DEBUG
#endif

#include <culprit>

#ifdef DEBUG_WAS_DEFINED
#define _DEBUG
#endif

让我知道这是否适合你。

【讨论】:

    猜你喜欢
    • 2014-05-14
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2022-01-03
    相关资源
    最近更新 更多