多态类实例拷贝后执行dynamic_cast出现段错误的原因是什么
问题原因分析
核心问题是你拷贝到buffer里的对象没有完成合法的构造,虚表指针是未初始化的垃圾值,dynamic_cast运行时做类型校验需要访问虚表,触发非法内存访问导致段错误。
具体拆解
C++中包含虚函数的类(你的Top类定义了虚析构函数,所以所有派生类都属于多态类)的对象内存布局固定包含一个虚表指针(vptr),存在对象内存的起始位置,指向对应类的虚函数表(vtable)。dynamic_cast、typeid这类依赖RTTI(运行时类型识别)的操作,都需要通过对象的虚表指针读取虚表里存的类型信息才能完成校验。
你代码里的错误出在对象拷贝的逻辑:
- 你执行
*memory = *dynamic_cast<T *>(this);时调用的是编译器生成的默认拷贝赋值运算符,默认赋值运算符只会拷贝类的用户定义非静态数据成员,绝对不会修改目标对象的虚表指针——虚表指针是对象构造阶段就确定的类型标识,不属于用户可拷贝的“数据内容”。 - 你用
reinterpret_cast把buffer强转为T*时,从来没有在这块内存上执行过T类的构造函数,这块内存里的所有值都是未初始化的垃圾值,包括虚表指针的位置存的也是非法地址。 - 你把
memory强转为Top*赋值给topPtr时只是做了地址转换,没有访问内存所以不会报错。 - 执行
dynamic_cast<T *>(topPtr)时,运行时会尝试通过topPtr指向的内存读取虚表指针,访问垃圾地址直接触发段错误。
修复方案
不要直接用赋值运算符拷贝对象,改用定位new(placement new)调用拷贝构造函数初始化buffer里的对象:
// 把原来的 *memory = *dynamic_cast<T *>(this); 替换为下面这行 new (memory) T(*dynamic_cast<T *>(this));
拷贝构造函数会完整初始化对象的虚表指针和所有数据成员,后续的dynamic_cast就可以正常执行。
用完buffer里的对象之后,需要手动调用析构函数释放资源:memory->~T();
内容的提问来源于stack exchange,提问作者rfk
相关产品推荐
相关产品推荐

