【问题标题】:"Mixing a dll boost library with a static runtime is a really bad idea..."“将 dll boost 库与静态运行时混合是一个非常糟糕的主意......”
【发布时间】:2012-03-20 15:02:24
【问题描述】:

我在 Visual Studio 解决方案中有两个项目。一个构建静态 LIB,另一个构建动态 DLL。两者都使用静态运行时链接(/MT 和 /MTd),并且都使用 Boost。 Boost 不是我的决定——我想放弃它,但被委员会否决了。

LIB 构建良好,但 DLL 从 auto_link.hpp(第 354 行)中咳出一个错误:“将 dll boost 库与静态运行时混合是一个非常糟糕的主意......”。

#if (defined(_DLL) || defined(_RTLDLL)) && defined(BOOST_DYN_LINK)
#  define BOOST_LIB_PREFIX
#elif defined(BOOST_DYN_LINK)
#  error "Mixing a dll boost library with a static runtime is a really bad idea..."
#else
#  define BOOST_LIB_PREFIX "lib"
#endif

我没有定义 BOOST_DYN_LINK。似乎 Boost 正在实现飞跃,因为我正在构建一个 DLL(定义了 _USRDLL 和 _WINDLL),我必须需要动态运行时链接(/MD 或 /MDd,它定义了 _DLL)或针对 Boost 的 DLL 链接。这是不正确的,因为我特别要求静态链接(/MT 或 /MTd)。

我针对 Boost 的错误假设提交了bug report,但这对我使用该库没有帮助。在报告中,Boost 维护者坚持认为我正在设置它(尽管审计表明我不是;并且 Boost 在至少 30 个文件中操纵它)。我在 Boost 邮件列表中找到了one answer,它实质上声明要更改我的项目设置以适应 Boost。

更改为动态运行时链接(/MD 和 /MDd)是不可行的,因为选择了静态链接 (1) 出于安全考虑,并且 (2) 另一个库使用静态链接。这是没有商量余地的——我们别无选择。

为了清楚起见总结(TLDR):我想对所有内容使用静态链接,而我的输出程序是 DLL(不是静态 LIB,不是 EXE)。一切都在 DLL 中静态链接。

有谁知道如何在 Windows 上使用这个库来构建一个带有静态链接的 DLL?

【问题讨论】:

  • 你能从 auto_link.hpp 中删除有问题的检查吗?或者在包含 auto_link.hpp 之前 #undef _USRDLL 和 _WINDLL 然后重新定义它们?
  • 几周前我刚刚处理了这个问题,但我不记得我脑海中的细节了。我们有一个针对静态 CRT 和静态提升构建的 DLL,并且没有错误/警告。如果到时候没人接,我明天去看看。
  • 应该注意的是,构建一个静态链接到 C 运行时库的 DLL 是非常危险的。这意味着在一个 DLL 中分配的内存不能在另一个 DLL 中直接释放。这听起来可能不会发生,但它可以。你会从中得到随机崩溃。
  • 这不仅仅适用于静态 CRT。如果您使用与不同版本的动态 CRT 链接的 DLL,则会遇到同样的问题。
  • @noloader:问题似乎是在某处定义了 BOOST_DYN_LINK。我认为您应该找到它的定义位置,因为我认为它不应该是。如果我尝试使用 /MTd 构建您的错误报告(正则表达式)中给出的最小示例并构建为 .dll,它似乎工作得很好(就像 boost 家伙说的那样)。您是否尝试构建那个最小的示例?

标签: c++ windows visual-c++ boost dll


【解决方案1】:

短版:听听 Boost ML 的人。 Boost 不支持你正在尝试做的事情,无论如何这是一个坏主意。最好接受这一点并让其他库使用动态运行时。

加长版:

您似乎误解了 Boost 告诉您的内容。您正在尝试解析 Boost 源代码,而不是仅仅阅读它的内容:

auto_link.hpp(第 354 行):“将 dll boost 库与静态运行时混合是一个非常糟糕的主意……”。

Boost 认为您正在构建一个 DLL,同时静态链接到运行时库。这正是您正在做的事情; Boost 已准确检测到您要执行的操作。

您的问题是 Boost 库不支持被构建到未动态链接到运行时库的 DLL 中。原因是这是“一个非常糟糕的主意”。因此,他们会检查您是否正在尝试这样做,并通过一条错误消息来停止您的构建,提醒您这一事实。

Boost 中不知道如何使某些东西“开箱即用”工作的“freetards”阻止了这种情况,因为静态链接到 DLL 中的运行时通常是用户的错误。它要么是偶然发生的,要么是由于对这可能造成的主要问题的无知。

如果您静态链接到运行时,每个 DLL/exe 都将拥有自己的运行时副本,并带有自己的全局变量。而且由于 heap 是通过全局变量管理的,这意味着每个 DLL/exe 都将拥有自己的堆。因此,如果您尝试释放分配在另一个地址空间中的内存...繁荣。如果你不小心的话,这比你想象的要容易得多。

这也可能导致其他问题。 “freetards”试图阻止你在脚下射击自己。但显然你知道最好不要“把他们的废话强加给诚实和毫无戒心的用户”,因为他们可能希望在他们即将驶过悬崖时得到建议。

现在,您可以简单地删除错误消息。 Boost 的大部分内容都是标头,因此只要您实际上没有链接到它的任何 .lib,就应该没问题。但是,我猜想“auto_link.hpp”仅被 .libs 的 Boost 部分使用,很可能你遇到它的事实开始意味着你正在尝试链接到 Boost .lib。

更改为动态运行时链接(/MD 和 /MDd)是不可行的,因为选择了静态链接 (1) 出于安全考虑,并且 (2) 另一个库使用静态链接。

如果考虑到安全性,您应该意识到这一点:您正在构建 DLL 的事实意味着您的应用程序可能对 DLL 注入开放,无论您如何链​​接到运行时。所以我看不出动态链接比静态链接更不安全。

【讨论】:

  • 我认为这是不对的。 auto_link.hpp 正在检查 _DLL,它是根据您要链接的 CRT 而不是您正在构建的项目类型定义的。 boost 带有与静态 CRT 链接的库的预构建版本;我们在 DLL 中使用它们就好了。显然,出于您所说的原因,我们不会在 DLL 的接口中使用 boost 类。
  • 当然定义很重要;这就是错误消息的依据。我同意某些配置选项在某处不正确,但可以构建原始问题中描述的配置。 boost 以多种配置提供二进制文件,其中之一是将 boost 作为与静态 CRT 链接的静态库。我们将它链接到一个 DLL 中没有问题。
  • @HarryJohnston 当说“堆”时,您假设只有一个堆。有多个堆,每个 C 运行时实例都会创建它的堆 - 这就是问题所在。
  • "Boost 认为您正在构建一个 DLL,同时静态链接到运行时库。这正是您正在做的事情;Boost 已经准确地检测到您正在尝试做什么。" - 我没有尝试使用 Boost DLL。我正在构建一个 DLL,我想将 Boost 作为静态 LIB 导入(就像我正在使用的所有其他库一样)。
  • @noloader,如果 DLL 是 Boost 的首选,我不明白为什么 C 运行时库不首选它。你坚持你选择的设置是在为失败做准备——事情会无缘无故地繁荣。这就是错误试图告诉你的。
【解决方案2】:

这个问题确实是提升设置的问题。 出于某种未知原因(我无法确定这是合乎逻辑的——因为它没有效果)。无论用户选项如何,Boost Python 都会强制动态链接 boost

简而言之,如果您的项目中有 boost-python,boost 会错误地阻止 boost 与 /MT 开关的静态链接。

通过在包含 boost 标头之前定义 BOOST_PYTHON_STATIC_LIB 可以轻松解决此问题。

【讨论】:

  • 我会接受这个以帮助未来的访问者,因为这似乎是一个合理的答案。但对未来的访客有一个警告:我无法对其进行测试。
  • 您能否具体说明定义 BOOST_PYTHON_STATIC_LIB 的含义。库的绝对路径?我有这个错误,似乎无法破解它。只有一行示例代码?
  • @bw4sz ,在包含 boost 标头 #define BOOST_PYTHON_STATIC_LIB 之前,或者将其设置为 IDE/Makefile 中的预处理器定义
【解决方案3】:

我不知道它是如何影响构建的,但是使用 -DCMAKE_BUILD_TYPE=Relase 运行 cmake 会有所帮助。可能这里提到的标志之一是 Release 的默认值。

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 2018-08-17
    • 2010-10-15
    • 2010-09-10
    • 2013-11-25
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2012-05-06
    相关资源
    最近更新 更多