ASAN检测到ODR违反了与动态加载的库共享的类vtable [英] ASAN detects ODR violation of vtable of class which is shared with dynamically loaded library

查看:498
本文介绍了ASAN检测到ODR违反了与动态加载的库共享的类vtable的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我正在一个项目中,该项目具有一个 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 错误。问题是 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 并可能在运行代码之前先进行 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屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆