STL和发布/调试库混乱

dim*_*mba 10 c++ linux gcc shared-libraries

我正在使用第三方.我正在使用它的共享库版本,因为库很大(~60MB)并且被多个应用程序使用.

有没有办法在应用程序启动时发现库的发布/调试版本分别用于我的应用程序的发布/调试版本?

更长的描述

暴露C++接口的库.其中一种API方法返回std::vector<std::string>.

我在调试模式下编译应用程序时的问题,应该使用库的调试版本.同样的发布.如果使用了不正确的库版本,应用程序将崩溃.

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

但是对于可以使用调试模式或发布模式basic_string对象的混合模式标准库,事情会变得更复杂

PS 1

看起来Timbo的提议是一种可能的解决方案 - 使用不同的soname来调试和发布库.那么,应该将什么传递给./configure脚本来更改库的名字?

PS 2

我的问题不是在链接时,而是在运行时.

PS 3

是一个问题,展示了我面临的问题.

Emp*_*ian 7

引用调试模式这里没有做调试或发布应用程序的构建.STL调试模式由-D_GLIBCXX_DEBUG和激活,是一种特殊的检查模式.

第三方库实际上不太可能使用STL检查模式进行编译,但如果是,则很可能会很快提及您的代码也应该编译-D_GLIBCXX_DEBUG.

如果第三方库没有使用检查STL构建,那么无论您是在进行优化还是调试构建,它都与您的代码兼容.

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

Valgrind和GDB是你的朋友.


Bro*_*ses 5

我相信您误读了您提供的链接上的文档.特别是,您误解了其目的 - 该部分名为"目标",并描述了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"(其中给定容器对象的所有使用必须使用相同的标志进行编译,但是在程序中使用相同的容器类不需要使用相同的方法编译flags),但这与提供所需交叉链接能力的完整"单元编译"不同.特别是,文档说明了这种交联能力,

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

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

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