我使用共享库时出现问题(Win 10中为.dll)。
我在两个不同的配置中构建一个名为xlib的lib,并尝试在名为xlibtest的项目中通过CMake测试它们。
工作流程是:
步骤A.构建xlib => xlib.dll + xlib.lib(仅符号)+ xlib.pdb [可选]
步骤B.构建xlibtest并链接xlib.lib => xlibtest.exe
如果在步骤A和步骤B中构建配置不同,那么当我运行xlibtest.exe时,会出现问题。 例如,我有一个功能
//xlib.h
void foo(std::string input);
在xlib中,当我调用此函数时它会崩溃。
//xlibtest.cpp
int main() {
xlib::foo("test"); // in debug mode I found the string pass to foo is wrong
}
我已经搜索并找到了有关此问题的一些解释。这可能是因为调试和发布配置的内存模式不同。并且建议不要混用这两种配置,即在调试配置中使用debug lib并在发布配置中释放lib。
然后是问题所在。我可以构建自己的两个版本的库。但是我可以为那些外部库做些什么呢?
我在项目中使用了英特尔MKL库,并在调试和发布配置中链接了相同的库。看起来效果很好。
但是当我使用Boost库时,调试版和发布版之间可能存在差异,因为我们可以在安装Boost库时决定我们构建的版本。
P.S。我之所以不与静态库链接的原因是编译时存在错误,需要相同的配置(即调试/发布)。
- 更新 -
我正在使用:
CMake 3.5.2;
编译器:用于Intel 64 VS2015环境的Intel icl 16.0 update 3;
IDE:VS 2015社区;
操作系统:Windows 10,64位。
CPU:Intel i7 4930K
很抱歉没有提供有关工具链的这些信息。我以前认为这是一个普遍的问题,与我使用的工具链无关。 @Hans Passant
我认为来自@John D的回答可能会让我感到困惑。在我了解到混合调试和发布配置存在问题后,我无法理解为什么使用英特尔MKL库没有区别,这就是我发布此问题的原因。这是因为英特尔MKL lib是一个没有std :: string的C lib吗?
答案 0 :(得分:0)
从技术上讲,库的“Debug”和“Release”版本是使用不同的编译器开关和预处理器宏构建的。它与编译具有可选功能的库没有根本的区别。
DEBUG
宏启用具有各种运行时检查和诊断的代码块。后者可能包括向数据类型添加成员。因此,您构建的C ++代码的调试和发布版本在一般情况下是二进制不兼容的。
这代表C ++标准库的代码。虽然它通常不是每次都从stratch编译,而是插入少数预编译版本之一(包括委托给a的“thunk”版本) DLL)。
如果您有两个模块
, 会出现问题问题主要发生在动态链接中(但是如果预先构建的静态库与其标题不对应,也可能在静态链接中发生)。
如果模块已编译(使用有问题的类型)并链接(使用有问题类型的库代码)对定义该类型的库的二进制不兼容版本,则会发生这种情况。
因此,特别是对于C ++标准库,要避免和/或修复它们,您需要
libgcc
) - 例如可能需要在它们之间传递例外。如果您的环境如此异构以至于无法实现,那么完全放弃C ++类型作为交换格式可能是明智的。(指定正确的模块并命名自己的模块,以便区分它们)
在链接时(静态或动态),没有“构建配置”这样的东西。所有这些都有很多模块。所有链接器都看到对其他模块(仅动态链接)和导出/导入条目的引用。它所做的就是找到引用的模块(再次,仅动态;在静态中,通常明确指定模块),然后将导出和导入的条目匹配在一起。 C ++导出/导入条目名称包含编码(“损坏”)形式的条目的整个签名(具体而言,不兼容的编译器必须使用不同的修改方案,因此它们生成的条目不会发生冲突。
链接器区分两个版本库的唯一方法是:
3)通常不实用(需要大量样板代码),并且在动态链接中,如果没有2),则无法使用,因为链接器首先匹配模块名称。 1)(搜索路径风味)不会缩放。
总结:
_d
后缀,版本后缀)