ASAN 检测到与动态加载库共享的类 vtable 的 ODR 违规

Fla*_*ire 6 c++ shared-libraries one-definition-rule address-sanitizer

我正在开发一个项目,该项目有一个“util”库,其中包含日志记录、断言处理等内容。它被编译成添加了静态库的静态库-fPIC。我还有一个插件系统,其中插件是在运行时通过dlopen. 这些插件和主要可执行文件都使用静态 util 库。

问题:现在我AddressSanitizer: odr-violation在使用 ASAN 时遇到错误。该问题size=40 'vtable for StdStreamWriter'报告了两次,其中 StdStreamWriter 是静态库内部使用的接口的实现。

我非常努力地在 MWE 中重现这一点:

  • 创建一个静态库,公开一些函数
  • 里面使用 std::shared_ptr 中的接口和实现
  • 创建一个共享库链接
  • 创建一个链接静态库和dlopen共享库的可执行文件

CMakeLists.txt

cmake_minimum_required(VERSION 3.8)
project(proj)

set(sanitizer_flags "-fsanitize=address,undefined -fno-omit-frame-pointer")
string(APPEND CMAKE_CXX_FLAGS " ${sanitizer_flags}")
string(APPEND CMAKE_EXE_LINKER_FLAGS " ${sanitizer_flags}")
string(APPEND CMAKE_MODULE_LINKER_FLAGS " ${sanitizer_flags}")

add_library(foo STATIC foo.cpp)
target_compile_features(foo PUBLIC cxx_std_14)
set_target_properties(foo PROPERTIES CXX_EXTENSIONS OFF POSITION_INDEPENDENT_CODE ON)
add_library(lib SHARED lib.cpp)
target_link_libraries(lib foo)
add_executable(main main.cpp)
target_link_libraries(main foo dl)
Run Code Online (Sandbox Code Playgroud)

然而,无论我多么努力,这个问题都不会出现在 MWE 中。

我将差异追溯到以下方面的不同结果nm -C liblib.so | grep vtable

  • MWE(无 ODR 错误)显示V vtable for Impl
  • 实际程序显示D vtable for StdStreamWriter

我猜这个错误源于Dvs 的差异V,导致vtables 没有被合并。

这种差异从何而来?这是什么时候决定的?我将共享库的链接命令精简为最基本的 ( clang++-8 -shared -fsanitize=address,undefined -o <..> <all *.o and *.so>),但仍然得到了D vtable而不是V vtable.

我还能尝试什么来解决这个问题?

yug*_*ugr 5

这很可能是由 Clang 的 Asan 实现中的一个已知问题引起的,该问题导致它检测到具有模糊链接的静态数据(通常是类 vtable 或 typeinfo)的错误 ODR 违规。

作为解决方法,请尝试在运行代码之前进行编译-mllvm -asan-use-private-alias=1并可能执行此操作。export ASAN_OPTIONS=use_odr_indicator=1

如果这解决了您的问题,请在上述问题中发表评论,以增加在上游彻底解决该问题的机会。