我最近尝试使用boost序列化来序列化包含std::vector<std::unique_ptr<Base>>>
作为成员的类。根据 boost 文档 (https://www.boost.org/doc/libs/1_71_0/libs/serialization/doc/serialization.html#derivedpointers(,我们必须使用存档的方法register_type
注册派生类,以便序列化正常工作。一切确实构建并运行良好,但地址清理器构建(在我们的 CI 中运行(失败并出现以下错误:
ASAN:DEADLYSIGNAL
=================================================================
==3==ERROR: AddressSanitizer: SEGV on unknown address 0x000000100000 (pc 0x559bc5f18288 bp 0x7ffe74fd8d30 sp 0x7ffe74fd8d10 T0)
==3==The signal is caused by a READ memory access.
==3==Hint: address points to the zero page.
#0 0x559bc5f18287 in boost::serialization::void_cast_detail::void_caster_primitive<Derived, Base>::void_caster_primitive() /usr/include/boost/serialization/void_cast.hpp:188
#1 0x559bc5f1714a in boost::serialization::singleton<boost::serialization::void_cast_detail::void_caster_primitive<Derived, Base> >::get_instance()::singleton_wrapper::singleton_wrapper() /usr/include/boost/serialization/singleton.hpp:117
#2 0x559bc5f173be in boost::serialization::singleton<boost::serialization::void_cast_detail::void_caster_primitive<Derived, Base> >::get_instance() /usr/include/boost/serialization/singleton.hpp:118
#3 0x559bc5ef3294 in __static_initialization_and_destruction_0 /usr/include/boost/serialization/singleton.hpp:155
...
在检查void_cast.hpp
中的内容时,我发现了void_caster_primitive
构造函数中存在问题的代码:
/* note about displacement:
* displace 0: at least one compiler treated 0 by not shifting it at all
* displace by small value (8): caused ICE on certain mingw gcc versions */
reinterpret_cast<std::ptrdiff_t>(
static_cast<Derived *>(
reinterpret_cast<Base *>(1 << 20)
)
) - (1 << 20)
从代码和注释来看,这个表达式正在计算Base
类在Derived
内的位移。然而,它看起来仍然像魔术,尤其是将(看似(随机数投射到Base
指针时。如果有人能阐明为什么这实际上计算了位移,那就太好了。
编辑: 下面是一个使用上面显示的位移计算方法的简单示例: https://godbolt.org/z/Bmp7zH 如果关闭了消毒器,它会编译并运行,但在打开后,程序会异常终止。
这也是在编译器资源管理器上重现 SEGV 的原始问题的尝试: https://godbolt.org/z/w8ZNx8 但是,链接提升序列化似乎不起作用,而且如果我打开清理器选项,构建有时会超时。
这个问题实际上不是由 Asan 引起的,而是由UBsan 引起的,它在转换期间执行类类型的验证(通过读取和分析对象的 vptr(。尝试在假地址读取内存会导致您的情况崩溃。
这是编译器中的一个错误,所以我强烈建议向清理器开发人员报告:
- 在海湾合作委员会布吉拉
- (如果问题与 Clang 重现(在 Github 跟踪器上