混合STL调试/发布库

Mixing STL debug/release libraries

本文关键字:布库 调试 STL 混合      更新时间:2023-10-16

我知道,混合调试和发布库,相互传递STL容器会导致大问题。但是在"调试"或"发布"中究竟是什么导致了这种情况?

我有一个QT项目,被构建为"发布",但它有/DEBUG添加到编译器标志。如果我在"调试"下构建另一个QT项目(也有/debug标志),它们兼容吗?

或者有一个优化标志或其他标志使它们不兼容?

基本上,有没有一种方法可以让我看到两个库的编译行,并看到一些东西说"不要混合这些!"?

这是未定义的行为,所以它可能会工作,但更有可能它会崩溃你的应用程序。这也取决于stl的实现,在调试版本中,它可能会启用额外的检查并分配额外的内存,使数据布局在发布模式中不同。最后,这违反了ODR规则(一个定义规则),再次导致未定义的行为。

我有一个QT项目,被构建为"发布",但它有/DEBUG添加到编译器标志。如果我在"调试"下构建另一个QT项目(也有/debug标志),它们兼容吗?

如果你的版本包含与调试完全相同的编译器标志,那么我会说它们是兼容的。

或者有一个优化标志或其他标志使它们不兼容?

你应该能够看到这些标志,我不认为优化标志应该导致UB问题,而是在编译阶段使用不同的宏导致ODR冲突。也许有一些优化标志可以改变结构中的对齐方式…

基本上,有没有一种方法可以让我看到两个库的编译行,并看到一些东西说"不要混合这些!"?

我不知道。

为什么要混合不同的构建库?这是自找麻烦。

不完全是。关于Visual c++的STL实现,有一些容器的数据成员对应于迭代器检查,只有在设置了一些预处理器变量时才会编译。这些变量是基于NDEBUG预处理器变量的默认值,它是"不调试"的准标准。但这些也可以直接从命令行、头文件或Visual Studio属性页等设置。

。:所有容器都派生自_Container_base,而这是一个取决于_ITERATOR_DEBUG_LEVEL的类型定义。不同的_Container_base实现有不同的内存布局,这就是导致调试版本和发布版本之间不兼容的原因。

/DEBUG编译器标志告诉编译器是否生成调试信息,也可能影响优化设置的默认值,但我不确定,当然这取决于编译器。

就像可以有一个不依赖于任何预处理器指令的STL实现,在这种情况下,无论你如何编译,调试或发布,内存布局将是相同的,因此它可以在以不同方式编译的模块之间传递。

首先,/DEBUG标志实际上并不创建"调试"构建。它只是告诉链接器生成调试信息,并在生成的二进制文件中创建一个.pdb文件。

至于调试版和发布版msvc++运行时的区别,问题在于不同的运行时对于同一个对象可以有不同的大小。例如,在调试中,可能会在迭代器中放置额外的信息,以确保它们在运行时的有效性。如果代码是根据这些结构的发布版本编译的,那么很可能会损坏。另一个问题是,如果一个对象从一个运行时的堆中分配,并试图在另一个运行时的堆中释放。