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

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

我正在一个具有“ 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之差引起的,这导致vtable无法合并。

这种区别从何而来?什么时候决定的?我将共享库的链接命令简化为基本要点(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的实现中出现了known issue,导致它使用vague linkage(通常是类vtables或typeinfos)为静态数据检测到错误的ODR违规。

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

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

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