VC ++库冲突问题

时间:2010-01-09 21:05:46

标签: c++ qt vtk

我正在开发一个使用Qt(gui lib),VTK(图形库)和另一个如此模糊的库的C ++项目,我不会提到它的名字,而是将其称为LIB_X。该项目使用Qt作为gui组件和VTK(更准确地说是VTK提供的支持Qt的QVTKWidget扩展)来渲染几何体。它使用LIB_X来收集和操作几何体。

问题是事实证明LIB_X实际上使用了VTK(我不知道在哪里和如何,它是闭源)。起初没有问题,编译时两个lib链接都很顺利,但是在某些时候我调用了某个(并且非常需要的)LIB_X函数并且编译导致了一些关于已经定义的VTK lib / obj的'blah blah'在LIB_X dll'错误。

e.g。 (并注意这是/ FORCE:MULTIPLE所以这是一个警告,请告诉我你是否想要没有/ FORCE的错误:MULTIPLE我将发布它):

1>LIB_X.lib(LIB_X.dll) : warning LNK4006: "public: __thiscall std::vector<double,class std::allocator<double> >::~vector<double,class std::allocator<double> >(void)" (??1?$vector@NV?$allocator@N@std@@@std@@QAE@XZ) already defined in vtkCommon.lib(vtkInformationDoubleVectorKey.obj);

我尝试使用/ FORCE:MULTIPLE,它起初似乎是一个奇迹,但我在代码中得到随机错误,这些错误通常会导致堆错误。我决定从主项目中删除对LIB_X的所有引用,并创建一个可以处理所有LIB_X内容的静态库。我不是C ++专家,所以我不确定当你使用预编译的lib时它是如何处理lib冲突的,但是当我将静态lib链接到我的主项目时仍然会收到lib冲突错误,所以我仍然必须使用/ FORCE:MULTIPLE。

一旦我拥有了静态库,似乎随机错误就消失了,我可以通过静态库在主项目中使用LIB_X方法做很多事情,但是无处不在,我添加了一个新的数据成员我的主项目的类(一个std :: vector of double)突然间我在我的一个静态库的方法中遇到了堆错误。如果我注释掉了新的数据成员,那么静态库的方法就可以了。我讨厌给出当前的错误,因为说实话,我不确定是否值得检查它,但无论如何它都是有帮助的:

注意:它在第151行崩溃到xutility,弹出断言: “file:dbgheap.c line:1279 expression:_CrtIsValidHeapPointer(pUserData)”

将矢量矢量double添加到矢量矢量矢量double,在push_back行上崩溃后出现错误:

std::vector<std::vector<double>> tmpVec;
for(srvl_iter = srvl.begin(); srvl_iter != srvl.end(); ++srvl_iter)
{
 tmpVec.push_back((*srvl_iter).getControlPoints());
}
this->_splines.push_back(tmpVec); //CRASH

当我向主项目添加一个新的数据成员(与静态库分开!)时,它才开始崩溃。注释掉新的数据成员会消除错误。

std::vector<std::vector<std::vector<double>>> _geometry; 

所以,/ FORCE:MULTIPLE似乎很糟糕,我得到的随机错误对我来说没有意义。还有其他解决方案吗?我搞砸了吗?我可以用LIB_X链接VTK吗?

2 个答案:

答案 0 :(得分:1)

在将我的应用程序链接到库(称为库LIB_Y)时,我遇到了大量LNK4006错误,这些库大量使用了std::vector<std::string>,我也在我的应用程序中执行了此操作。经过一些实验,我找到了一个有效的解决方案 - 将LIB_Y包装在一个单独的DLL中,该DLL调用LIB_Y(例如LIB_Y_WRAPPER),然后将主应用程序链接到LIB_Y_WRAPPER。

要试用我的建议,您需要:

  1. 将“处理所有LIB_X内容的静态库”从静态LIB项目更改为DLL项目(我将称之为LIB_X_WRAPPER)。
  2. 确保LIB_X_WRAPPER的头文件不包含任何LIB_X头文件。这是非常重要的,因为包装器需要将您的应用程序与LIB_X头文件中声明的数据类型(例如std::vector<double>)完全隔离。仅从LIB_X_WRAPPER的源文件中引用LIB_X的头文件。
  3. 更改静态库中所有类和函数的声明,以确保它们是从DLL导出的(如果需要有关从DLL导出的详细信息,请参阅this answer。)
  4. 这个解决方案对我有用,因为它保持了LIBY使用的std::vector<std::string>类的实例化(编译器生成的函数)与我的应用程序中std::vector<std::string>的实例化完全分开。

    顺便说一句,我怀疑你看到崩溃的原因(你在std::vector<double>的析构函数中评论它)是因为你的应用程序中std::vector<double>的实例化不同于LIB_X。

答案 1 :(得分:0)

评论可能只是随机的运气 - 如果你破坏了堆你并不总是立刻看到它,但是stl向量将分配和释放左右的东西,所以难怪它发现错误。

有些lib要求您按特定顺序包含内容。我不确定为什么究竟是因为对我来说似乎放弃并说你不能正确设计一个图书馆,但这是一个可悲的事实。只要你没有在你包含vtk的任何地方包含这个lib_x,它应该没问题。

然而,他们可能会争夺一些资源或使用不正确的东西,使他们无法一起工作。如果你能够通过隔离它们来使编译工作正常并且它仍然失败那么是的,你只是运气不好,因为它只是设计这个lib_x的方式失败了,因为它是如此模糊,它不太可能是彻底调试所有用途。当某些东西没被广泛使用时,它通常最终会成为开发人员的机器和项目上的东西,但不一定是其他人的东西。