STL 和发布/调试库混乱

发布于 2024-10-13 00:00:44 字数 854 浏览 4 评论 0原文

我正在使用一些第三方。我正在使用它的共享库版本,因为该库很大(~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 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(4

旧人 2024-10-20 00:00:44

此处引用的调试模式没有任何内容处理应用程序的调试或发布版本。 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.

笑,眼淚并存 2024-10-20 00:00:44

我相信您误读了您提供的链接中的文档。特别是,您误解了它的目的——该部分的标题是“目标”,并描述了 C++ 调试库的许多假设设计以及这些设计的后果,以便解释所做的实际设计选择。您引用的行后面的文本片段描述了由于假设实现对发布模式和调试模式字符串具有单独设计而导致的混乱。它接着说:

因此,我们无法轻松地为 std::basic_string 类模板提供安全的迭代器,因为它存在于整个 C++ 标准库中。

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

...

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

换句话说,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:

For this reason we cannot easily provide safe iterators for the std::basic_string class template, as it is present throughout the C++ standard library.

(Or, rephrasing that, providing a special "debug" version of string iterators is impossible.)

...

With the design of libstdc++ debug mode, we cannot effectively hide the differences between debug and release-mode strings from the user. Failure to hide the differences may result in unpredictable behavior, and for this reason we have opted to only perform basic_string changes that do not require ABI changes. The effect on users is expected to be minimal, as there are simple alternatives (e.g., __gnu_debug::basic_string), and the usability benefit we gain from the ability to mix debug- and release-compiled translation units is enormous.

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 to std::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,

We believe that this level of recompilation is in fact not possible if we intend to supply safe iterators, leave the program semantics unchanged, and not regress in performance under release mode....

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.

似狗非友 2024-10-20 00:00:44

为 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.

腻橙味 2024-10-20 00:00:44

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

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

例如,如果您正在使用 make:

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

This is the sort of check you should be doing in your build system. In your build script,

  • if you're building for release then link against the release library.
  • if you're building for debug then link against the debug library.

For instance, if you're using make:

release: $(OBJ)
    $(CC) $(CXXFLAGS_RELEASE) $(foreach LIB,$(LIBS_RELEASE),-l$(LIB))
debug: $(OBJ)
    $(CC) $(CXXFLAGS_DEBUG) $(foreach LIB,$(LIBS_DEBUG),-l$(LIB))
~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文