混合使用不同编译器版本构建的二进制文件

Posted

技术标签:

【中文标题】混合使用不同编译器版本构建的二进制文件【英文标题】:Mixing binaries built with different compiler's versions 【发布时间】:2013-10-14 12:16:08 【问题描述】:

我想知道,调用代码是否可以放置在使用不同工具链构建的 .dll 中?是否使用 .lib 文件和旧编译器构建代码来构建可能的新代码?

我知道,第二个不太可取,但我想知道,是不是不可能。

正是我的情况是这样的:

我有 a.exe 使用 VC7.1 构建的文件,使用 b.lib 文件,该文件也是使用 VC7.1 构建的。 a.exe 调用来自 c.dll 的代码,该代码也是使用 b.dll 构建的。现在我想写一个新的c.dll,但是用VC9编译。 (我想这样做,因为我需要一些不支持使用 VC7.1 构建它们的库。)——我的c.dll 也需要b.lib,我仍然有它的源代码,因此我可以重新编译它.

那么,有可能让它工作吗?如果不是,您能否提供一个简短的解释,究竟是什么不允许这样做?

【问题讨论】:

一个大问题是您将获得不同的 CRT,这意味着您将获得不同的堆。这会导致释放问题。 【参考方案1】:

这并非完全不可能。主要问题是您将不可避免地得到运行时库的两个 不同副本。每个都保持自己的状态并使用自己的内存分配器的副本。 DLL 接口必须经过精心设计,以避免可能导致的事故。

硬性规则是您永远不能从 DLL 中的代码中抛出异常并在 EXE 中捕获它。并且您不能从 DLL 代码中返回标准 C++ 库对象,例如 std::string,它们具有不同的实现,并且 EXE 无法正确销毁该对象,因为它使用了不同的分配器。更一般的规则是,DLL 永远不能返回指向需要由调用者释放的对象的指针。 CRT 状态可能会导致微妙的问题,例如 errno 未返回正确的错误代码和区域设置错误。总而言之,大量的痛苦很难诊断,甚至更难修复。

COM 编程模型就是一个安全的例子。它从不公开实现,只公开纯抽象接口。没有例外,只有错误代码。对象由工厂分配并进行引用计数。在绝对必要的情况下,它使用一个公共堆从 CoTaskMemAlloc() 进行分配。这不是一个流行的编程模型,但它需要它。

【讨论】:

以上是关于混合使用不同编译器版本构建的二进制文件的主要内容,如果未能解决你的问题,请参考以下文章

vs2010指定的文件格式无法识别或为不支持的二进制

python如何编译生成二进制文件?

使用不同的 signkey 重建黑莓二进制文件

如何从二进制文件中获取应用程序的版本号?

设置ARC有效或者无效

对于不同版本的 Microsoft Visual C++,编译的 .lib 文件是不是可以互换?