ASAN 检测与动态加载库共享的类的 vtable 的 ODR 违规
ASAN detects ODR violation of vtable of class which is shared with dynamically loaded library
我正在做一个项目,该项目有一个"util"库,其中包含日志记录,断言处理等内容。这被编译成一个静态库,并添加了-fPIC
。我还有一个插件系统,其中插件是在运行时通过dlopen
加载的共享库。这些插件和主可执行文件都使用静态实用程序库。
问题:现在我在使用 ASAN 时遇到AddressSanitizer: odr-violation
错误。size=40 'vtable for StdStreamWriter'
报告了两次此问题,其中 StdStreamWriter 是静态库中内部使用的接口的实现。
我非常努力地在MWE中重现这一点:
- 创建一个公开某个函数的静态库 在
- 里面使用一个接口和实现在 std::shared_ptr
- 创建与之链接的共享库
- 创建针对静态库的可执行文件链接并
dlopen
共享库
CMakeList.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
我想错误源于D
与V
的差异,这导致 vtables 未合并。
这种差异从何而来?什么时候决定?我将共享库的链接命令精简为基本要素(clang++-8 -shared -fsanitize=address,undefined -o <..> <all *.o and *.so>
(,但仍然获得D vtable
而不是V vtable
。
我还能尝试什么来解决这个问题?
这很可能是由 Clang 的 Asan 实现中的一个已知问题引起的,该问题导致它检测具有模糊链接的静态数据(通常是类 vtables 或 typeinfos(的错误 ODR 违规。
作为解决方法,请尝试使用 -mllvm -asan-use-private-alias=1
进行编译,并在运行代码之前执行export ASAN_OPTIONS=use_odr_indicator=1
。
如果这解决了您的问题,请在上述问题中发表评论,以增加在上游一劳永逸地修复它的机会。
- 这是 basic.def.odr 部分的缺陷吗?
- 为什么显式模板实例化不会破坏 ODR?
- 纯虚拟类和错误未定义对 'vtable 的引用
- (ODR 使用问题)在不同文件中priority_queue名称相同的结构
- 声明中不一致的no是否违反ODR?
- 对植物的 vtable 的未定义引用?
- 如何查看在程序级别为我的程序创建了多少 vtable 和 vpointer
- 是否使用静态 constexpr 变量 odr?
- 使用 -pthread 如何不违反 ODR 规则?
- 未定义的符号缺少 vtable
- 编译器是否会创建vtable,而不考虑在c++中创建对象
- 为什么重复的空基存储不与 vtable 指针重叠?
- 如何在生产中避免vtable查找,并且仍然能够在单元测试中进行广泛的模拟
- 在C中实现vtable而不是使用C++的目的
- 如果使用非公共类,vtable 是否会在二进制文件中持续存在?
- 为什么编译器不在同一翻译单元中警告 ODR 违规
- 关于这个在 Linux 上使用 gcc 编译的程序中的 vtable,nm 告诉我什么?
- C++ standard: ODR and constexpr std::string_view
- 使用多个命名空间对 vtable 的未定义引用
- ASAN 检测与动态加载库共享的类的 vtable 的 ODR 违规