C++ ABI

摘要

ABI被人熟知,就是编译时,接口不匹配导致运行时的动态库undefined symbol报错。

ABI (Application Binary Interface)

  • ABI:应用程序二进制接口(ABI)是两个二进制程序模块之间的接口。z
  • 在编译时,我们需要保持接口版本的统一,才能正常通过编译。
  • 通常,其中一个模块是库(e.g.,动态库libstdc++.so)或操作系统功能,另一个是用户正在运行的程序。

组成

library API + compiler ABI = library ABI^1 ,为了编译顺利进行我们需要保持

  1. library API(Application Programing Interface)
    1. e.g., types/functions/exceptionsSTH in (STL) include files
  2. compiler ABI(Application Binary Interface)
    1. sth during the compilation process, e.g., alignment/funcNameHandling

默认版本

  • 在 GCC 5 及以后的版本中,默认使用 C++11 ABI(即 -D_GLIBCXX_USE_CXX11_ABI=1)。这意味着新编译的代码将遵循 C++11 的 ABI 规范。
  • 对于旧版本的 GCC,默认使用的是旧的 ABI(-D_GLIBCXX_USE_CXX11_ABI=0)。

查看编译器的预定义宏

你可以使用 -dM -E 选项来查看预定义宏,包括 ABI 相关的宏。可以执行以下命令:

1
echo | g++ -dM -E -x c++ - | grep _GLIBCXX_USE_CXX11_ABI
  • 如果输出是 #define _GLIBCXX_USE_CXX11_ABI 1,表示当前使用的是 C++11 ABI。
  • 如果输出是 #define _GLIBCXX_USE_CXX11_ABI 0,表示使用的是旧的 ABI。
  • 如果没有输出,可能是没有定义该宏,表示使用的编译器可能较老或没有显式设置。

设置与修改

CMake

CMake 本身不会直接设置 ABI 选项,但会继承所用编译器的默认设置。
可以在 CMakeLists.txt 中显式设置 ABI 选项,例如:

1
add_definitions(-D_GLIBCXX_USE_CXX11_ABI=1)

编译器

显式版本切换的标志是 -fabi-version

检查

在 pintool 编译过程中:

1
2
3
#if !defined(__GXX_ABI_VERSION) || CC_USED_ABI_VERSION != __GXX_ABI_VERSION
#error 您的编译器的 C++ ABI 与 pin 工具包的 ABI 不匹配。
#endif

实践

PTA编译严重依赖torch的环境

ABI的开启严重依赖已有的正确的torch

参考文献

Author

Shaojie Tan

Posted on

2023-10-09

Updated on

2025-01-30

Licensed under