混合使用不同编译器版本构建的二进制文件
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() 进行分配。这不是一个流行的编程模型,但它需要它。
【讨论】:
以上是关于混合使用不同编译器版本构建的二进制文件的主要内容,如果未能解决你的问题,请参考以下文章