【问题标题】:ASAN detects ODR violation of vtable of class which is shared with dynamically loaded libraryASAN 检测到与动态加载的库共享的类的 vtable 的 ODR 违规
【发布时间】:2019-12-14 20:47:22
【问题描述】:

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

问题:现在我在使用 ASAN 时遇到 AddressSanitizer: odr-violation 错误。问题是 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(无 ODR 错误)显示 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

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

【问题讨论】:

  • 我建议在Asan tracker 中提交一个错误(他们会要求您使用最新的 Clang 进行复制)。
  • 我希望我可以创建一个复制品来帮助我调查并可能解决问题。但是我尝试过的任何 MWE 都不会遇到 D vtable 的事情
  • 我知道已经一年了,但这是 Clang 还是 GCC?
  • 是Clang,见倒数第二段
  • 你能尝试用-mllvm -asan-use-private-alias=1 编译吗?如果可行,我会准备完整的答案。

标签: c++ shared-libraries address-sanitizer one-definition-rule


【解决方案1】:

这很可能是由 Clang 的 Asan 实现中的 known issue 引起的,这会导致它检测到带有 vague linkage(通常是类 vtables 或 typeinfos)的静态数据的错误 ODR 违规。

作为一种解决方法,请尝试使用-mllvm -asan-use-private-alias=1 进行编译,并可能在运行您的代码之前使用export ASAN_OPTIONS=use_odr_indicator=1

如果这解决了您的问题,请在上述问题中发表评论,以增加在上游一劳永逸地解决问题的机会。

【讨论】:

  • @Jean-François Fabre 我删除了另一个问题的重复答案,并投票决定将其关闭为 dup。
猜你喜欢
  • 2018-07-31
  • 2019-12-13
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2019-09-02
  • 1970-01-01
  • 2015-10-21
相关资源
最近更新 更多