我有一个恼人的问题,我可能会以某种方式规避,但另一方面更愿意在它之上,并了解究竟发生了什么,因为看起来这些东西真的存在。
以下是故事:我有一个简单的OpenGL应用程序可以正常工作:从来不是编译,链接或运行它的主要问题。现在我决定尝试将一些更密集的计算转移到工作线程中,以便可能使GUI更具响应性 - 当然使用Boost.Thread。
简而言之,如果我在.cpp文件的开头添加以下片段:
#include <boost/thread/thread.hpp>
void dummyThreadFun() { while (1); }
boost::thread p(dummyThreadFun);
,然后在尝试启动Debug构建时,我开始收到“此应用程序无法启动,因为未找到MSVCP90.dll”。 (发布模式正常。)
现在看看使用Dependency Walker的可执行文件,他也找不到这个DLL(我猜这是预期的),我可以看到我们正在寻找它以便能够调用以下函数:
?max@?$numeric_limits@K@std@@SAKXZ
?max@?$numeric_limits@_J@std@@SA_JXZ
?min@?$numeric_limits@K@std@@SAKXZ
?min@?$numeric_limits@_J@std@@SA_JXZ
接下来,我尝试将min
和max
的每个实例转换为使用宏,但可能无法找到对它们的所有引用,因为这没有帮助。 (我正在使用一些我没有源代码的外部库。但即使我能做到这一点 - 我认为这不是正确的方法。)
所以,我的问题 - 我猜 - 是:
我在Visual Studio 2008的一个非常简单的安装中首先使用它。然后尝试安装Feature Pack和SP1,但它们也没有帮助。当然也试过多次重建。
我正在使用Boost的预建二进制文件(v1.36.0)。这不是我第一次在这个项目中使用Boost,但这可能是我第一次使用基于单独源的部件。
禁用增量链接无济于事。该程序是OpenGL的事实似乎也不相关 - 我在将一行代码添加到一个简单的控制台程序中时遇到了类似的问题(但它抱怨MSVCR90.dll和_mkdir
当我用boost::create_directory
替换后者时,问题就消失了!)。它实际上只是删除或添加使程序运行正常或根本不运行的那三行。
我不能说我理解并排(甚至不知道这是否相关,但这就是我现在所假设的),说实话,我也不是超级感兴趣 - 只要我可以构建,调试和部署我的应用程序......
编辑1:在尝试构建一个无论如何都能重现问题的精简示例时,我发现该问题与the Spread Toolkit有关,其使用方法是我所有程序遇到此问题的常见因素。 (但是,在开始链接Boost之前我从来没有这样做过。)
我现在想出了一个让我重现这个问题的最小程序。它由两个编译单元A.cpp和B.cpp组成。
A.cpp:
#include "sp.h"
int main(int argc, char* argv[])
{
mailbox mbox = -1;
SP_join(mbox, "foo");
return 0;
}
B.cpp:
#include <boost/filesystem.hpp>
一些观察结果:
SP_join
行,问题就会消失。(在方案2和3中,程序在调用SP_join
时崩溃,但这只是因为邮箱无效......这与手头的问题无关。)
另外,Spread的核心库是链接的,这肯定是我的问题#1的答案的一部分,因为我的系统中没有该lib的调试版本。
目前,我正在尝试提出一些可以在其他环境中重现问题的方法。 (即使我真的可以在我的场所外重复,我会感到非常惊讶......)
编辑2:好的,所以here我们现在有了一个软件包,我可以在WinXP32 + VS2008 + Boost 1.36.0的几乎香草安装上重现这个问题。仍pre-built binaries from BoostPro Computing)。
罪魁祸首肯定是Spread lib,我的构建在某种程度上需要一个相当古老的STLPort版本用于 MSVC 6 !尽管如此,我仍然觉得这些症状相对有趣。此外,如果你能真正重现这个问题 - 包括上面的方案1-3,那将是很好的。包装很小,应该包含所有必要的部分。
事实证明,问题与Boost.Thread没有任何关系,因为这个例子现在使用Boost Filesystem库。此外,它现在抱怨MSVCR90.dll,而不是之前的P。
答案 0 :(得分:2)
Boost.Thread有很多可能的构建组合,以尝试和满足MSVC可能的链接方案的所有差异。首先,您可以静态链接到Boost.Thread,也可以链接到单独的DLL中的Boost.Thread。然后,您可以链接到MSVC运行时的DLL版本或静态库运行时。最后,您可以链接到调试运行时或发布运行时。
Boost.Thread标头尝试使用编译器生成的预定义宏自动检测构建方案。为了链接使用调试运行时的版本,您需要定义_DEBUG
。这是由/ MD和/ MDd编译器开关自动定义的,所以它应该没问题,但是你的问题描述也是如此。
你从哪里获得预先建立的二进制文件?您是在项目设置中明确选择库,还是让自动链接机制选择适当的.lib文件?
答案 1 :(得分:1)
这是一个经典的链接错误。看起来你是linking to a Boost DLL本身链接到错误的C ++运行时(还有this page,对“线程”进行文本搜索)。它看起来像boost::posix::time
库链接到正确的DLL。
不幸的是,我找不到讨论如何选择正确构建的Boost DLL的页面(虽然我找到了一个似乎指向BOOST_THREAD_USE_DLL
和BOOST_THREAD_USE_LIB
的{{3}} )。
再次查看您的答案,您似乎正在使用预先构建的二进制文件。您无法链接到的DLL是three-year-old email(该页面上的第二个问题)。 part of the TR1 feature pack。或者你需要一个不同的二进制文件来链接。显然,boost::posix::time
库链接了未修补的C ++运行库。
由于您已经应用了功能包,我认为我将采取的下一步是手动构建Boost。这是我一直采用的路径,它非常简单:That feature pack is available on Microsoft's website,并在库源中运行Boost Build脚本。就是这样。
答案 2 :(得分:1)
我相信我过去曾遇到过与Boost相同的问题。根据我的理解,它发生是因为Boost头使用预处理器指令链接到正确的lib。如果您的调试和发布库位于同一文件夹中且名称不同,则“自动链接”功能将无法正常工作。
我所做的是为我的项目定义BOOST_ALL_NO_LIB(这会阻止标题“自动链接”),然后使用VC项目设置链接到正确的库。
答案 3 :(得分:1)
看起来其他人已经回答了问题的Boost方面。这里有关于MSVC方面的一些背景知识,可能会进一步让人头疼。
有四种版本的C(和C ++)运行时可能:
DLL版本仍然需要链接到那个静态库(它以某种方式将所有设置都链接到运行时的DLL - 我不知道细节)。请注意,在所有情况下,调试版本都具有d
后缀。 C运行时使用c
中缀,C ++运行时使用cp
中缀。看模式?在任何应用程序中,您都应该只链接到其中一行中的库。
有时(就像你的情况一样),你发现自己链接到其他人的静态库,该库被配置为使用错误版本的C或C ++运行时(通过非常烦人的#pragma comment(lib)
)。您可以通过提高链接器的详细程度来检测这一点,但它是一个真正的PITA来寻找。 “使用火箭筒杀死啮齿动物”解决方案是使用/nodefaultlib:...
链接器设置来排除您不需要的6 C和C ++库。我过去曾经没有用过这个问题,但我不肯定它会一直有效......也许有人会从木工中走出来告诉我这个“解决方案”可能会导致你的程序在周二下午吃掉婴儿
答案 4 :(得分:0)
现在这变得更有趣......如果我只是在源代码中添加它:
boost::posix_time::ptime pt = boost::posix_time::microsec_clock::universal_time();
(连同相应的#include
东西),然后再次正常工作。所以这是一个快速而不是太脏的解决方案,但是嘿 - 这里发生了什么,真的吗?
答案 5 :(得分:0)
从内存中,boost库的各个部分需要您定义一些预处理程序标志,以便能够正确编译。类似于BOOST_THREAD_USE_DLL
等等。
BOOST_THREAD_USE_DLL
不会导致此特定错误,但可能期望您定义_DEBUG
或类似的错误。我记得几年前在我们的boost C ++项目中,我们在visual studio编译器选项(或makefile)中声明了很多额外的BOOST_XYZ
预处理器定义
检查boost thread目录中的config.hpp
文件。当您提取ptime
内容时,它可能包含一个不同的config.hpp
文件,然后可能会以不同的方式定义这些预处理器。