ABI发布和调试之间的兼容性

ABI Compatibility between release and debug

本文关键字:之间 兼容性 调试 ABI      更新时间:2023-10-16

使用GCC时,考虑到我有时在发布时编译同一个库,有时在调试时编译,ABI是否保证兼容?

(使用相同的编译器时)

我有一个可执行文件和一些共享对象(有些依赖于其他对象),我希望能够交换发布/调试共享对象,而无需重新编译所有内容只有感兴趣的共享对象。

这可能吗,或者在某种情况下,我可能会以这种方式得到一些未定义的行为?(假设我的代码被严格打包,并在发布和调试中填充)


编辑:

我将详细说明我们所看到的问题。我们有一个自定义版本的intrusive_ptr,在调试模式下,我们有自己的intrusive_ptr,它有一个单个成员,即boost::intrusive_ptr,在发布版中,我们只使用boost::intrusive_ptr。我们的intrusive_ptr的API与boost::intrusive_ptr相同,并且我们在类中没有任何虚拟函数
我们看到的是:
如果我们使用所有调试库或所有发布库,一切都会很好。如果我们将调试可执行文件与发布库混合使用,则intrusive_ptr存在内存泄漏,并且它不会发布对象。

我们的intrusive_ptrboost::intrusive_ptr的大小在调试和发布中都是相同的(我们的类在顶部没有添加任何大小开销)。

所以我想知道是什么导致了泄漏,ABI的差异是我唯一想到的。

想法?

我知道有几个编译器会生成不兼容的代码用于发布和调试(尽管这些编译器早就被弃用了)。从表面上看,我不相信对象模块是完全兼容的,除非它们是用完全相同的标志编译的。

这就是为什么makefile(遵循GNU原则)和类似IDE的Eclipse将发布/调试/概要文件对象构建到不同的目录中。以确保它们永远不会被混淆。

通常不会,因为发布和调试构建之间的通常区别只是使调试步骤更好地工作的选项。但是,如果在发布版本和调试版本之间以不同的方式定义其他选项(如整数大小、目标体系结构等),则调用方参数可能与被调用方的期望值不匹配,则仍有可能出现意外行为。还可能存在异常安全性问题,以及运行时链接器可能无法检查的常量。