我知道混合使用STL容器的调试版和发布库会导致很大的问题。但究竟在'调试'或者'发布'导致这个?
我有一个QT项目,它被构建为' release',但它已将/ DEBUG添加到编译器标志中。 如果我在' debug'下构建另一个QT项目(也有/ DEBUG标志),它们兼容吗?
或者是否有优化标志或其他标志使它们不兼容?
基本上,有没有一种方法可以查看2个库的编译行,看到的内容是" DON' T MIX THESE!"?
答案 0 :(得分:2)
这是未定义的行为,因此它可能会起作用,但更可能会导致应用程序崩溃。它还取决于stl实现,在调试版本中,它可能启用额外的检查并分配额外的内存,使数据布局在发布模式下不同。最终,这违反了ODR规则(一个定义规则),再次导致未定义的行为。
我有一个QT项目,它被构建为'release',但它已将/ DEBUG添加到编译器标志中。如果我在'debug'(也有/ DEBUG标志)下构建另一个QT项目,它们是否兼容?
如果您的Release包含与Debug完全相同的编译器标志,那么我会说它们是兼容的。
或者是否有优化标志或其他标志使它们不兼容?
你应该能够看到那些标志,我不认为优化标志会导致UB问题,它在编译阶段使用的相当不同的宏会导致ODR违规。也许有优化标志可以改变结构中的对齐...
基本上,有没有办法可以查看2个库的编译行,并看到“不要混合它们”的内容?
不知道。
为什么首先要混合使用不同的构建库?这是在寻找麻烦。
答案 1 :(得分:1)
不是真的。关于Visual C ++的STL实现,对应于迭代器检查的容器的数据成员仅在设置了一些预处理器变量时才编译。这些变量是基于NDEBUG预处理器变量的默认值,该变量是"无调试"的准标准。但这些也可以直接从命令行设置,也可以从头文件或Visual Studio属性页等设置。
例如:所有容器都来自_Container_base
,而这是一个取决于_ITERATOR_DEBUG_LEVEL
的typedef。不同的_Container_base
实现具有不同的内存布局,这就是导致调试版和发行版之间不兼容的原因。
/ DEBUG编译器标志告诉编译器是否生成调试信息,也可能影响优化设置的默认值,但我不确定,当然这取决于编译器。
就像可能有一个不依赖于任何预处理器指令的STL实现,在这种情况下,无论你如何编译,调试或发布,内存布局都是相同的,所以它可以通过模块之间用不同的方式编译。
答案 2 :(得分:1)
首先/DEBUG
标志实际上并没有创建调试'建立。它只是告诉链接器生成调试信息并创建一个.pdb文件以及生成的二进制文件。
关于调试和发布MSVC ++运行时之间的区别,问题在于不同的运行时可以为同一对象具有不同的大小。例如在调试中,可能会将额外信息放在迭代器中以确保它们在运行时的有效性。如果已针对这些结构的发布版本编译代码,则可能存在损坏。另一个问题是,如果一个对象从一个运行时的堆中分配,并且试图在另一个运行时的堆上释放。