使用GCC检测ABI兼容性问题

10

我最近花了相当长时间追查问题,最终发现是使用-D_GLIBCXX_DEBUG编译库(告诉libstdc++使用带有额外检查的标准库的调试版本),但没有使用此选项编译客户端程序所致。这导致ABI兼容性问题。

是否有一种方式可以使用GCC自动检测到类似的问题?Visual Studio提供了detect_mismatch pragma,我认为这将达到这个目的,但我不知道是否有GCC等效的方法。GCC会嵌入一个符号名(例如GLIBCXX_3.4.9),我可以想象一些方案会因为不存在相应的符号(例如mylib_debug_stl)而导致链接错误,但我能想到的唯一获取该符号的方法都很巧妙。

或者,其他人如何避免这个问题?构建已检查版本的库并使用不同的名称或类似方法?

2个回答

4

有没有办法使用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;
  // ...
};

然后,当我想要在特定类中使用Debug Mode vector时,我会更改预处理条件,而不会影响程序中的所有容器。由于更改涉及向文件写入(因此更新其时间戳),任何依赖该标头的内容都将通过make重新构建,并且有两种不同类型的容器,std::vector<int>__gnu_debug::vector<int>,它们具有不同的符号,链接器不会混淆。
只定义_GLIBCXX_DEBUG不会导致重建所有依赖项,并且会在全局范围内静默地更改std::vector的定义,而不是将特定容器更改为具有不同名称的不同类型,__gnu_debug::vector

我尝试了--detect-odr-violations(使用Gold),但它对我的问题保持沉默。我回到了文档,从中我可以看出,你建议使用命名空间别名实际上与GNU的libstdc++尝试做的有些相似;他们将非调试容器放入std::__cxx1998,发布容器放入std::__debug,然后使用命名空间关联(“内联命名空间”)将适当的命名空间引入std范围内。[续] - EvanED
我的理解是它应该也避免了链接器问题...这让我想知道库中是否有一个“错误”,导致它在我的情况下无法检测到。 - EvanED
让我们在libstdc++列表上继续这个话题。 - Jonathan Wakely
@JonathanWakely 它不会悄悄地更改定义——名称更改,如果您重新构建部分但不是所有需要重新构建的部分,则应该会出现链接错误(未解析的符号)。 - Employed Russian
@EmployedRussian,参见我在http://gcc.gnu.org/ml/libstdc++/2012-10/msg00077.html中给出的示例,它会导致一种不影响任何混淆符号和不引起链接器错误但会导致运行时错误的含义静默改变。 - Jonathan Wakely

0
原来是使用-D_GLIBCXX_DEBUG编译库(告诉libstdc++使用带有额外检查的标准库的调试版本),但未对客户端程序进行编译所导致的问题。明确的libsdc++调试模式设计目标是支持这种配置,我有些怀疑这是否是您问题的真正原因。重新构建不带-D_GLIBCXX_DEBUG的库后问题可能已经消失,但这并不能证明ABI不兼容是根本原因。

(1) 我有一个程序,在不一致的_GLIBCXX_DEBUG设置下构建时会崩溃,但是当以任何方向使用一致的设置编译时,它不仅没有崩溃,而且在valgrind中也没有问题。(2) libstdc++ 模式的明确目标是检测此类错误,但正如Jonathan Wakely在上面链接的(http://gcc.gnu.org/ml/libstdc++/2012-10/msg00077.html)那样,他们没有完全实现这个目标。(从我的理解来看,除非得到GCC C++编译器和链接器的明确支持,否则将无法实现。) - EvanED

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接