【问题标题】:Runtime Issues While Mixing Libraries from Different Versions of Visual Studio混合来自不同版本 Visual Studio 的库时的运行时问题
【发布时间】:2010-12-29 04:51:40
【问题描述】:

我在运行使用两个不同版本的 Visual Studio 构建的项目时遇到了意外的访问错误。我的一般配置如下:

  • LibA 是静态库,静态运行时链接,msvc 8.0
  • LibB 是静态库,静态运行时链接,msvc 9.0
  • 我的集成目标项目是一个 msvc 9.0 COM dll,它静态链接上述库

此项目已构建,但在运行时因某些 STL 代码中的访问冲突而崩溃。堆栈似乎表明我在调用流插入运算符期间已经通过了两个版本(8 和 9)的标头。我意识到这是一个问题。

不知何故,这个电话:

ost << std::dec << port_; //(originating from an object in LibA)

...通过以下堆栈跟踪下降:

std::basic_ostream::operator<<(...) (ostream:283, msvc 8.0 version <-- expected, since LibA was built with this version)
std::num_put::put(...) (xlocnum:888, msvc 8.0 version <-- expected, since LibA was built with this version)
std::num_put::do_put(...) (xlocnum:1158, msvc 9.0 version!! !@#$!%! <-- not expected, since LibA was built with msvc 8.0)
std::ios_base::flags() (xiosbase:374, msvc 9.0 version <-- follows from above)

访问冲突发生在 std::ios_base::flags() 中。我怀疑这是由于调用堆栈中的实现混合造成的(虽然我不确定)。

我的问题是。

1.) 这种访问冲突的可能原因是混合了 msvc 标头实现吗?
2.) 有没有办法防止这些实现混合在一起?
3.) 有没有更好的方法来配置这三个项目以进行集成(假设从 msvc 8.0 迁移 LibA 是不可取的)?

我知道this questionthis one 中提出的想法。这里我最感兴趣的是这个具体问题,如果有什么办法可以避免。

我们将不胜感激。

【问题讨论】:

    标签: windows visual-studio visual-c++ linker


    【解决方案1】:

    您不能在同一个项目中使用不同的 STL 实现。这意味着甚至来自同一编译器的不同版本。如果您的 LibA 具有接受 std::vector 作为参数的函数,则您只能从构建 LibA 的 STL 传递向量对象。这就是为什么许多 C++ 库只公开 C API 的原因。

    要么更改 API,要么使用相同的编译器重新构建所有项目。

    你正在做你不应该做的事情。您处于未定义行为的世界中。尝试调试这个特定的崩溃是没有意义的。即使您设法使这条线路正常工作,您也会在其他地方遇到新的崩溃。

    【讨论】:

    • 有了这个特定的问题,我什至还没有到在库之间传递数据的地步。这是对来自 LibA 的 operator
    • @Adam:调试器可能会谎报您要进入的标头(因为它很困惑)。或者它可能无关紧要,因为链接器在两个相同的实现之间进行了选择。尼古拉是对的。你在未定义的领域。您需要修复构建而不是调试症状。
    • @Adrian:我曾考虑过调试器具有误导性的可能性,但我认为调试符号可能包含完整路径(因此调试器区分了标头“xlocnum”的两个版本在同一个调用堆栈中)。我也同意这是未定义的领域。我有兴趣了解是否有一种方法可以防止这种无意混合同一个调用堆栈。听起来好像答案是“不”。
    • @Adam:这是您调用堆栈的可能解释stackoverflow.com/questions/1948204
    【解决方案2】:

    不保证 MSVC 主要版本之间的库二进制兼容性。 STL 代码主要是扩展为您的代码的模板代码。所以你的静态库中可能有不兼容的 STL 代码块。

    一般来说,这应该不是问题,除非 STL 代码是库接口的一部分。例如,如果您将迭代器或对向量的引用从一个库传递到另一个库,那么您就有麻烦了。

    最好的解决方案是使用相同版本的编译器构建所有内容。如果你不能这样做(例如,如果其中一个库来自第三方),你可能会被卡住。

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 2010-09-21
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2017-08-09
      • 1970-01-01
      相关资源
      最近更新 更多