【问题标题】:Detecting ABI compatibility issues with GCC使用 GCC 检测 ABI 兼容性问题
【发布时间】:2012-09-19 16:53:28
【问题描述】:

我最近花了相当多的时间来追踪一个问题,这个问题原来是由使用 -D_GLIBCXX_DEBUG 编译库引起的(它告诉 libstdc++ 使用带有额外检查的标准库的调试版本)但是编译没有客户端程序。这导致了 ABI 兼容性问题。

有什么方法可以自动检测 GCC 的此类问题吗? Visual Studio 提供了detect_mismatch pragma,我认为它可以达到这个目的,但我不知道有任何 GCC 等价物。 GCC 做了一些嵌入符号名称(例如GLIBCXX_3.4.9)的事情,我可以想象如果相应的符号(例如mylib_debug_stl)不存在,由于未定义符号而导致链接错误的方案,但我唯一的方法能想出使用那个符号真的很hacky。

另外,其他人如何避免这个问题?将库的检查版本构建为不同的名称或类似名称?

【问题讨论】:

    标签: debugging gcc g++ glibc abi


    【解决方案1】:

    有什么方法可以让我使用 GCC 自动检测此类问题吗?

    只有链接器可以检测您是否链接了不兼容的代码,而不是编译器。

    备用链接器gold 可以检测--detect-odr-violations 选项的一些问题。

    另外,其他人如何避免这个问题?将库的检查版本构建为不同的名称或类似名称?

    我只是确保在我想使用调试模式时重建所有内容,我认为我从来没有想要保留一个使用调试模式构建的库。它是用来调试的,不是正常使用的。

    无论如何,我很少使用-D_GLIBCXX_DEBUG,我更经常这样做:

    #if 0
    # include <debug/vector>
    namespace my_class_stl = __gnu_debug;
    #else
    #include <vector>
    namespace my_class_stl = std;
    #endif
    
    struct my_class
    {
      typedef my_class_stl::vector<int> container;
      typedef container::iterator iterator;
      // ...
    };
    

    然后,当我想为该特定类使用调试模式向量时,我会更改预处理器条件,而不影响程序中的每个容器。因为更改涉及写入文件(并因此更新其时间戳)任何依赖于该标头的内容都将由 make 重建,并且有两种不同的类型,std::vector&lt;int&gt;__gnu_debug::vector&lt;int&gt;,它们具有不同的符号并且可以不要被链接器弄糊涂了。

    仅定义_GLIBCXX_DEBUG 不会导致所有依赖项都重新构建,并且会在全局范围内默默地更改std::vector 的定义,而不是将特定容器更改为具有不同名称的不同类型__gnu_debug::vector

    【讨论】:

    • 我尝试了 --detect-odr-violations(使用 Gold),但它对我的问题保持沉默。我回到the documentation,据我所知,您使用命名空间别名的建议实际上有点类似于 GNU 的 libstdc++ 尝试做的事情;他们将非调试容器放入 std::__cxx1998,将发布容器放入 std::__debug,然后使用命名空间关联(“内联命名空间”)将适当的容器放入 std 中的范围。 [继续]
    • [继续] 我的阅读是它应该也避免链接器问题......这让我想知道库中是否存在导致它的“错误”在我的情况下不检测它。
    • 让我们继续这个 libstdc++ 列表
    • @JonathanWakely 它不会默默地改变定义——错位的名字会改变,如果你重建部分,你应该得到链接错误(未解析的符号),但不是全部这需要重建。
    • @EmployedRussian,请参阅我在 gcc.gnu.org/ml/libstdc++/2012-10/msg00077.html 给出的示例,其中 确实 获得了含义上的静默变化,不会影响任何损坏的符号,也不会导致链接器错误,但会导致运行时错误。
    【解决方案2】:

    原来是由于编译带有 -D_GLIBCXX_DEBUG 的库(它告诉 libstdc++ 使用带有额外检查的标准库的调试版本)但编译客户端程序时没有。

    这是一个显式 libsdc++ 调试模式设计目标来支持这种配置,我有点怀疑这是你问题的实际原因。

    在没有-D_GLIBCXX_DEBUG 的情况下重建库后问题可能已经消失,但这并不能证明ABI 不兼容是根本原因。

    【讨论】:

    • (1) 当 _GLIBCXX_DEBUG 设置不一致时,我有一个程序在构建时因错误的内存访问而崩溃,但当在任一方向使用一致的设置编译时,不仅没有崩溃,而且 valgrinded clean。 (2) 检测此类错误是libstdc++ 模式的明确目标,但正如上面链接的 Jonathan Wakely (gcc.gnu.org/ml/libstdc++/2012-10/msg00077.html),他们没有完全实现这一目标。 (据我了解,如果没有 GCC C++ 编译器和链接器的明确支持,将无法实现。)
    猜你喜欢
    • 2021-11-26
    • 2018-01-07
    • 2011-04-09
    • 2019-05-20
    • 2013-01-25
    • 2015-10-29
    • 1970-01-01
    相关资源
    最近更新 更多