我正在开发一个项目,它有一个“util”库,其中包含日志记录、断言处理等内容。它被编译成静态库-fPIC
添加。我还有一个插件系统,其中插件是在运行时加载的共享库dlopen
。这些插件和主要可执行文件都使用静态 util 库。
问题:现在我得到了AddressSanitizer: odr-violation
使用 ASAN 时出错。问题是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
我猜错误源于差异D
vs V
这会导致 vtable 不被合并。
这种差异从何而来?这是什么时候决定的?我将共享库的链接命令精简为最基本的部分(clang++-8 -shared -fsanitize=address,undefined -o <..> <all *.o and *.so>
)但仍然得到D vtable
代替V vtable
.
我还能尝试什么来解决这个问题?
这很可能是由已知问题在 Clang 的 Asan 实现中,它会使用以下命令检测静态数据的错误 ODR 违规模糊的联系(通常是类 vtable 或 typeinfo)。
作为解决方法,请尝试使用以下命令进行编译-mllvm -asan-use-private-alias=1
也许正在做export ASAN_OPTIONS=use_odr_indicator=1
在运行您的代码之前。
如果这解决了您的问题,请在上述问题中发表评论,以增加在上游彻底解决该问题的机会。
本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系:hwhale#tublm.com(使用前将#替换为@)