我正在做一个项目,这个项目有一个 "util "库,其中包含了诸如日志记录、断言处理等内容。这个库被编译成一个静态库,其内容是 -fPIC
添加。我还有一个插件系统,插件是共享库,在运行时通过 dlopen
. 这些插件和主执行程序都使用静态util库。
问题是:现在我得到的是 AddressSanitizer: odr-violation
使用ASAN时出现错误。这个问题是 size=40 'vtable for StdStreamWriter'
报告了两次,其中StdStreamWriter是静态库中内部使用的接口的实现。
我真的很努力地想在MWE中重现这个问题。
dlopen
共享图书馆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
:
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
.
我还可以尝试什么方法来解决这个问题?