ASAN检测到ODR违反了与动态加载的库共享的类vtable [英] ASAN detects ODR violation of vtable of class which is shared with dynamically loaded library
问题描述
我正在一个项目中,该项目具有一个 util库,其中包含诸如日志记录,断言处理等内容。此库被编译为一个静态库,并添加了 -fPIC
。我还有一个插件系统,其中的插件是在运行时通过 dlopen
加载的共享库。这些插件和主要可执行文件都使用静态util库。
I'm working on a project which has a "util" library containing stuff like logging, assertion handling etc. This is compiled into a static library with -fPIC
added. I also have a plugin system, where the plugins are shared libraries loaded at runtime via dlopen
. Those plugins and the main executable both use the static util library.
问题:现在我得到 AddressSanitizer:odr-violation $使用ASAN时出现c $ c>错误。问题是
size = 40'stdStreamWriter的vtable'
报告了两次,其中StdStreamWriter是静态库内部使用的接口的实现。
The problem: Now I'm getting AddressSanitizer: odr-violation
errors when using ASAN. The issue is size=40 'vtable for StdStreamWriter'
reported twice where StdStreamWriter is an implementation of an interface used internally in the static library.
我非常努力地在MWE中重现此内容:
I tried really hard to reproduce this in a MWE:
- 创建一个暴露某些功能的静态库
- 在其中使用接口和实现的std :: shared_ptr
- 创建与此链接的共享库
- create链接到静态库和
dlopen
共享库
- Create a static library exposing some function
- Inside that use an interface and implementation in a std::shared_ptr
- create a shared library linking against that
- create an executable linking against the static lib and
dlopen
the shared library
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中都不会出现此问题。
However the issue does not occur in the MWE no matter how hard I try.
我将差异归结为 nm -C liblib中的不同结果.so | grep vtable
:
- MWE(无ODR错误)显示Impl
V vtable
- 附加程序显示StdStreamWriter的
D vtable
- The MWE (no ODR error) shows
V vtable for Impl
- The acutal program shows
D vtable for StdStreamWriter
我想错误是由 D
与 V
之差引起的导致vtable不能被合并。
I guess the error stems from the difference D
vs V
which results in the vtables not being merged.
这种区别从何而来?什么时候决定的?我将共享库的链接命令简化为基本要素( clang ++-8 -shared -fsanitize = address,undefined -o< ..>< all * .o and * .so> ;
),但仍然获得 D vtable
而不是 V vtable
。
Where does this difference come from? When is this decided? I stripped down the link command for the shared library to the bare essentials (clang++-8 -shared -fsanitize=address,undefined -o <..> <all *.o and *.so>
) but still get the D vtable
instead of V vtable
.
我还可以尝试解决此问题吗?
What else can I try to fix this?
推荐答案
这很可能是由于是由Clang在Asan的实现中已知问题引起的,该错误导致其检测到错误的ODR违规行为具有模糊链接(通常是类)的静态数据vtables或typeinfos)。
This is most likely caused by a known issue in Clang's implementation of Asan which causes it to detect false ODR violations for static data with vague linkage (normally class vtables or typeinfos).
作为解决方法,请尝试使用 -mllvm -asan-use-private-alias = 1 $ c $进行编译c>并可能在运行代码之前先进行
export ASAN_OPTIONS = use_odr_indicator = 1
。
As a workaround, try compiling with -mllvm -asan-use-private-alias=1
and maybe doing export ASAN_OPTIONS=use_odr_indicator=1
before running your code.
如果这可以解决您的问题,请发表通讯尝试解决上述问题,以增加其在上游永久修复的可能性。
If this fixes your problem, please post a comment in the aforementioned issue to increase the chance that it's fixed once and for all in upstream.
这篇关于ASAN检测到ODR违反了与动态加载的库共享的类vtable的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!