STL 和发布/调试库混乱
我正在使用一些第三方。我正在使用它的共享库版本,因为该库很大(~60MB)并且被多个应用程序使用。
有没有办法在应用程序启动时找出库的发布/调试版本分别用于我的应用程序的发布/调试版本?
详细描述
公开 C++ 接口的库。其中一种 API 方法返回 std::vector
。
当我在调试模式下编译应用程序时出现问题,应该使用库的调试版本。发布时也一样。如果使用了错误版本的库,应用程序就会崩溃。
根据 gcc (参见 http://gcc.gnu.org/onlinedocs/libstdc++ /manual/bk01pt03ch17s04.html)
但具有混合模式标准库 可以使用调试模式 或释放模式 basic_string 对象, 事情变得更加复杂
复杂1
看起来 Timbo 的提议是一个可能的解决方案 - 对调试和发布库使用不同的 soname。那么,应该将什么传递给 ./configure 脚本来更改库 soname?
PS 2
我的问题不是在链接时,而是在运行时。
PS 3
这里是演示我面临的问题的问题。
I'm using some 3rd party. I'm using it's shared library version, since the library is big (~60MB) and is used by several applications.
Is there a way at application startup to find out that release/debug version of library is used respectively for release/debug version of my application?
Longer description
The library which exposes C++ interface. One of API methods return std::vector<std::string>
.
The problem when I compile my application in debug mode, debug version of the library should be used. Same for release. If incorrect version of the library is used application is crashed.
According to gcc (see http://gcc.gnu.org/onlinedocs/libstdc++/manual/bk01pt03ch17s04.html)
but with a mixed mode standard library
that could be using either debug-mode
or release-mode basic_string objects,
things get more complicated
P.S. 1
It looks like proposal of Timbo is a possible solution - use different soname for debug and release libraries. So, what should be passed to ./configure script to change library soname?
P.S. 2
My problem is not at link time, but rather at run time.
P.S. 3
Here is question demonstrating problem I is facing with.
如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。
绑定邮箱获取回复消息
由于您还没有绑定你的真实邮箱,如果其他用户或者作者回复了您的评论,将不能在第一时间通知您!
发布评论
评论(4)
此处引用的调试模式没有任何内容处理应用程序的调试或发布版本。 STL调试模式通过
-D_GLIBCXX_DEBUG
激活,是一种特殊的检查模式。第三方库实际上不太可能是使用 STL 检查模式编译的,但如果是的话,它很可能会立即提到您的代码也应该使用
-D_GLIBCXX_DEBUG
进行编译。如果第 3 方库不是通过检查 STL 构建的,那么无论您是进行优化构建还是调试构建,它都与您的代码兼容。
由于您声明与第 3 方库的优化构建链接的代码的调试版本会导致崩溃,因此该崩溃很可能是由代码中的错误(或者可能是第 3 方库中的错误)引起的。
Valgrind 和 GDB 是您的朋友。
The debug mode referenced here has nothing to do with debug or release build of your application. The STL debug mode is activated with
-D_GLIBCXX_DEBUG
and is a special checking mode.It is very unlikely that the 3rd party library was in fact compiled with STL checking mode, but if it was, it would likely very promptly mention that your code should also be compiled with
-D_GLIBCXX_DEBUG
.If the 3rd party library was not built with checking STL, then it is compatible with your code regardless of whether you are doing optimized or debug build.
Since you state that debug build of your code linked with optimized build of 3rd party library causes a crash, that crash is most likely caused by a bug in your code (or possibly by a bug in 3rd party library).
Valgrind and GDB are your friends.
我相信您误读了您提供的链接中的文档。特别是,您误解了它的目的——该部分的标题是“目标”,并描述了 C++ 调试库的许多假设设计以及这些设计的后果,以便解释所做的实际设计选择。您引用的行后面的文本片段描述了由于假设实现对发布模式和调试模式字符串具有单独设计而导致的混乱。它接着说:
(或者,换句话说,提供特殊的“调试”版本的字符串迭代器是不可能的。)
换句话说,GCC 的 libstdc++ 中的调试和发布模式的设计拒绝了这种假设的实现,对字符串进行了单独的设计,特别是为了允许您担心如何避免的那种跨模式链接。
因此,在不使用
-D_GLIBCXX_DEBUG
(或者出于某种原因,如果您愿意的话)的情况下编译一次库,并将其与应用程序的任一模式链接时,您应该不会遇到问题。如果您确实遇到问题,那是由于某个地方的错误造成的。 [但是请参阅下面的编辑!这是特定于std::string
的,而不是其他容器!]编辑:接受此答案后,我继续回答后续问题在 std::vector; crash ,并意识到这个答案的结论是错误的。 GCC 的 libstdc++ 对字符串进行了巧妙的处理,以支持“每次使用重新编译”(其中给定容器对象的所有使用都必须使用相同的标志进行编译,但程序中相同容器类的使用不需要使用相同的标志进行编译)标志),但这与提供您所需的交叉链接能力的完整“每单元编译”不同。特别是,该文件提到了这种交联能力,
因此,如果您在库接口中传递容器,您将需要两个单独的库。老实说,对于这种情况,我发现最简单的解决方案是将两个库安装到不同的目录中(每个变体一个 - 并且您希望它们都与主库目录分开)。或者,您可以重命名调试库文件,然后手动安装。
作为进一步的建议——您可能不会经常在调试模式下运行它。可能只值得将调试版本静态编译并链接到您的应用程序中,因此您不必担心安装多个动态库并在运行时保持它们正常。
I believe that you have misread the documentation at the link you provide. In particular, you've misunderstood its purpose -- that section is entitled "Goals", and describes a number of hypothetical designs for a C++ debug library and the consequences of those designs in order to explain the actual design choices that were made. The bits of text that follow the lines you quoted are describing the chaos that would result from a hypothetical implementation that had separate designs for release-mode and debug-mode strings. It goes on to say:
(Or, rephrasing that, providing a special "debug" version of string iterators is impossible.)
In other words, the design of the debug and release modes in GCC's libstdc++ has rejected this hypothetical implementation with separate designs for the strings, specifically in order to allow cross-mode linking of the sort that you are worrying about how to avoid.
Thus, you should not have problems with compiling your library once, without
-D_GLIBCXX_DEBUG
(or with it, if for some reason you prefer), and linking it with either mode of your application. If you do have problems, it is due to a bug somewhere. [But see edit below! This is specific tostd::string
, not other containers!]Edit: After this answer was accepted, I followed up in answering the follow-up question at std::vector<std::string> crash, and realized that the conclusion of this answer is incorrect. GCC's libstdc++ does clever things with strings to support "Per-use recompilation" (in which all uses of a given container object must be compiled with the same flags, but uses of the same container class within a program need not be compiled with the same flags), but that is not the same thing as complete "Per-unit compilation" that would provide the cross-linking ability you need. In particular, the documentation says of that cross-linking ability,
Thus, if you're passing containers across your library interface, you will need two separate libraries. Honestly, for this situation I've found that the easiest solution is just to install the two libraries into different directories (one for each variant -- and you'll want both to be separate from your main library directory). Alternately, you can rename the debug library file and then install it manually.
As a further suggestion -- you're presumably not running this in debug mode very often. It may be worth only compiling and linking the debug version statically into your application, so you don't have to worry about installing multiple dynamic libraries and keeping them straight at runtime.
为 DLL 的调试版本和发布版本指定不同的名称,并通过库依赖项链接正确的名称。然后,除非找到正确的 DLL,否则您的应用程序将不会启动。
Give the debug and release versions of the DLL different names and link the correct one through library dependency. Your application then wont start unless it finds the correct DLL.
这是您应该在构建系统中进行的检查。在构建脚本中,
例如,如果您正在使用 make:
This is the sort of check you should be doing in your build system. In your build script,
For instance, if you're using make: