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

ABI Compatibility between release and debug

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

(使用相同的编译器)

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

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


编辑:

我将详细说明我们遇到的问题。我们有一个自定义版本的 intrusive_ptr,在调试模式下我们有我们自己的 intrusive_ptr,它有一个 单个 成员,它是一个 boost::intrusive_ptr,并且在发布我们只需使用 boost::intrusive_ptr。我们的intrusive_ptr的API和boost::intrusive_ptr是一样的,class.
没有虚函数 我们看到的是:
如果我们使用所有调试库或所有发布库都可以正常工作。如果我们将调试可执行文件与发布库混合使用,intrusive_ptr 会发生内存泄漏,并且不会释放对象。

我们的 intrusive_ptrboost::intrusive_ptr 的大小在调试和发布时是相同的(我们的 class 不会在顶部增加任何大小开销)。

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

想法?

通常不会,因为发布版本和调试版本之间的通常区别只是使调试步进效果更好的选项。但是意外行为仍然是可能的,如果您在发布版本和调试版本之间定义不同的其他选项(例如整数大小、目标体系结构、??),则调用者参数可能与被调用者的期望不匹配。也可能存在异常安全问题,以及 运行 时间链接器可能无法检查的 const-ness。

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

这就是为什么 makefile(遵循 GNU 原则)和 IDE 像 Eclipse 将 release/debug/profile 对象构建到不同目录中的原因。确保他们永远不会混淆。