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

问题描述 投票:0回答:1

我正在做一个项目,这个项目有一个 "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)

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

我将这一差异归结为以下方面的不同结果 nm -C liblib.so | grep vtable:

  • MWE(无网上解决错误)显示: V vtable for Impl
  • 实验程序显示 D vtable for StdStreamWriter

我想这个错误是源于不同的 DV 导致vtables无法合并。

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

我还可以尝试什么方法来解决这个问题?

c++ shared-libraries address-sanitizer one-definition-rule
1个回答
1
投票

这很可能是由一个 已知问题 在Clang的Asan实现中,这将导致它检测到静态数据的错误ODR违规行为,并与 暧昧关系 (通常是类vtables或typeinfos)。

作为一个变通的办法,可以尝试用 -mllvm -asan-use-private-alias=1 也许在做 export ASAN_OPTIONS=use_odr_indicator=1 在运行你的代码之前。

如果这样就解决了你的问题,请在上述问题中发表评论,以增加在上游一次性修复的机会。

© www.soinside.com 2019 - 2024. All rights reserved.