删除new分配的指针时出现RtlValidateHeap无效地址错误是什么原因
错误触发原因
该报错的核心诱因是基类ObjectPrinter未定义虚析构函数,结合虚继承的内存布局特性触发了内存释放逻辑异常:
- 虚继承导致指针地址偏移:
ConsolePrinter采用虚继承方式派生自ObjectPrinter,派生类实例的内存布局中,基类子对象的地址和实例本身的堆分配起始地址不一致。你给出的运行状态也印证了这点:new返回的实例原始起始地址为0x00E1BF50,赋值给基类指针op1后,指针值变为0x00E1BF7C,指向的是派生类内部的基类子对象地址,并非堆分配的合法释放起点。 - 无虚析构导致释放地址错误:当执行
delete op1时,因为基类没有虚析构函数,编译器会直接按照ObjectPrinter类型的指针地址释放内存,也就是尝试释放0x00E1BF7C这个非堆分配起点的地址,传入RtlValidateHeap的地址不合法,直接触发堆校验错误。
修复方案
给基类ObjectPrinter添加默认虚析构函数即可:
#ifndef OBJECTPRINTER_H #define OBJECTPRINTER_H #include <typeinfo> class ObjectPrinter { public: // 新增虚析构函数 virtual ~ObjectPrinter() = default; virtual bool compatible(const ObjectPrinter* objprtr) const = 0; virtual void printObject() = 0; virtual const std::type_info& getType() const = 0; }; #endif
添加虚析构后,delete基类指针时会通过虚表找到派生类的析构逻辑,自动调整指针到堆分配的原始起始地址再释放,不会再出现地址校验错误。
内容的提问来源于stack exchange,提问作者The Eye
相关产品推荐
相关产品推荐

