STL和释放/debugging库混乱

我正在使用一些第三方。 我使用的是共享库版本,因为库很大(〜60MB),并被多个应用程序使用。

有没有办法在应用程序启动找出发行版/debugging版本的库分别用于我的应用程序的发布/debugging版本?

更长的描述

暴露C ++接口的库。 API方法之一返回std::vector<std::string>

当我在debugging模式下编译我的应用程序时,应该使用库的debugging版本。 相同的发布。 如果使用的库的版本不正确,则应用程序崩溃。

根据gcc(见http://gcc.gnu.org/onlinedocs/libstdc++/manual/bk01pt03ch17s04.html )

但是使用混合模式标准库可能会使用debugging模式或释放模式basic_string对象,事情变得更加复杂

PS 1

它看起来像Timbo的提案是一个可能的解决scheme – 使用不同的sonamedebugging和发布图书馆。 那么,应该传递给./configure脚本来改变库soname呢?

PS 2

我的问题不在于链接时间,而是在运行时。

PS 3

这是certificate我面临的问题的问题。

Solutions Collecting From Web of "STL和释放/debugging库混乱"

我相信你误解了你提供的链接上的文档。 特别是,你误解了它的目的 – 该部分的标题是“目标”,并描述了一些C ++调试库的假设设计以及这些设计的结果,以解释所做的实际设计选择。 所引用的行中的文本位正在描述由假设的实现引起的混乱,该实现具有用于发布模式和调试模式字符串的单独设计。 它继续说:

出于这个原因,我们不能轻易地为std :: basic_string类模板提供安全的迭代器,因为它存在于整个C ++标准库中。

(或者,换句话说,提供一个特殊的“调试”版本的字符串迭代器是不可能的。)

通过libstdc ++调试模式的设计,我们不能有效地隐藏用户调试和释放模式字符串之间的差异。 未能隐藏差异可能会导致不可预知的行为,因此我们选择只执行不需要ABI更改的basic_string更改。 由于有简单的选择(例如__gnu_debug :: basic_string),对用户的影响预计会很小,而且我们从混合调​​试和发布编译的翻译单元的能力中获得的可用性好处是巨大的。

换句话说,在GCC的libstdc ++中调试和发布模式的设计已经拒绝了这个假设的实现,为这个字符串设计了不同的设计,特别是为了允许你担心如何避免的那种交叉模式链接。

因此,如果没有-D_GLIBCXX_DEBUG (或者如果出于某种原因,如果您喜欢的话),并且将其与您的应用程序的任一模式进行链接,则不应该在编译您的库时遇到问题。 如果你确实有问题,这是由于某处的错误。 [但请参阅下面的编辑! 这是特定于std::string ,而不是其他容器!]

编辑:这个答案被接受后,我跟着回答在std :: vector <std :: string>崩溃的后续问题,并意识到这个答案的结论是不正确的。 GCC的libstdc ++对字符串进行了巧妙的处理,以支持“Per-use recompilation”(每次使用重新编译)(在这种情况下,给定容器对象的所有用途必须使用相同的标志进行编译,但是在程序中使用相同的容器类不需要编译标志),但这与提供所需交叉能力的完整“每单元编译”不同。 特别是文件中提到的交联能力,

我们认为,如果我们打算提供安全的迭代器,保持程序语义不变,并且在释放模式下不退化,那么这种重新编译的级别实际上是不可能的。

因此,如果你在你的库接口中传递容器,你需要两个独立的库。 老实说,对于这种情况,我发现最简单的解决方案就是将两个库安装到不同的目录中(每个变体都有一个 – 并且你希望两者都与主库目录分开)。 或者,您可以重命名调试库文件,然后手动安装它。

作为进一步的建议 – 你大概不会经常在调试模式下运行这个。 只需将调试版本静态编译并链接到您的应用程序中即可,因此您不必担心安装多个动态库并在运行时保持它们平直。

这里引用的调试模式与调试或发布应用程序的构建无关 。 STL调试模式使用-D_GLIBCXX_DEBUG激活,是一种特殊的检查模式。

实际上,第三方库实际上是用STL检查模式编译的,但是如果是这样的话,它可能会很快地提到你的代码也应该用-D_GLIBCXX_DEBUG编译。

如果第三方库不是通过检查STL来构建的,那么无论您是在进行优化还是调试构建,它都与您的代码兼容。

由于您声明代码的调试版本与第三方库的优化版本链接导致崩溃,该崩溃很可能是由您的代码中的错误(或可能由第三方库中的错误)引起的。

Valgrind和GDB是你的朋友。

给DLL的调试和发布版本不同的名称,并通过库依赖链接正确的一个。 除非找到正确的DLL,否则您的应用程序将无法启动。

这是您在构建系统中应该进行的检查。 在你的构建脚本中,

  • 如果您正在构建发布版本,则需要链接到版本库。
  • 如果您正在构建调试版,则需要链接到调试库。

例如,如果你使用make:

 release: $(OBJ) $(CC) $(CXXFLAGS_RELEASE) $(foreach LIB,$(LIBS_RELEASE),-l$(LIB)) debug: $(OBJ) $(CC) $(CXXFLAGS_DEBUG) $(foreach LIB,$(LIBS_DEBUG),-l$(LIB))