派生类错误向下转型导致运行时异常问题求助
问题分析与解决建议
你的代码触发std::__non_rtti_object异常的核心原因是野指针访问,具体问题出在construct函数中:
da_vec.push_back(std::unique_ptr<derivedA>(new derivedB(4)).get());
这里的std::unique_ptr是临时对象,当这条语句执行完毕后,临时unique_ptr会被销毁,同时自动释放它管理的derivedB对象。但你把get()返回的裸指针存入了vector,导致vector里的指针变成悬空指针(指向已被释放的内存)。后续在func中对这个悬空指针的引用做dynamic_cast时,因为对象已不存在,RTTI信息无法正常获取,进而触发该异常。
解决方法
方法1:改用智能指针容器存储(推荐)
直接使用std::vector<std::unique_ptr<derivedA>>管理对象,避免手动内存管理风险:
#include <iostream> #include <vector> #include <memory> class Base { public: int a; Base(int _a) : a(_a) {}; virtual void print() = 0; }; class derivedA : public Base { public: derivedA(int _a) : Base(_a) {}; void print() { std::cout << "dA" << std::endl; } }; class derivedB : public derivedA { public: derivedB(int _a) : derivedA(_a) {}; void print() { std::cout << "dB" << std::endl; } }; void construct(std::vector<std::unique_ptr<derivedA>>& da_vec) { da_vec.push_back(std::make_unique<derivedB>(4)); } void func(derivedA& da) { // 用指针版dynamic_cast判断转换是否成功,避免抛出异常 if (derivedB* db_ptr = dynamic_cast<derivedB*>(&da)) { db_ptr->print(); } else { std::cout << "转换为derivedB失败" << std::endl; } } int main() { std::vector<std::unique_ptr<derivedA>> da_vec; construct(da_vec); for (auto& da : da_vec) func(*da); }
通过std::make_unique创建智能指针并直接存入容器,确保对象生命周期由智能指针自动管理,不会出现悬空指针问题。同时改用指针版dynamic_cast,可以提前判断转换是否成功,避免转换失败时抛出std::bad_cast异常。
方法2:手动管理内存(不推荐,易出错)
如果必须使用裸指针容器,需手动控制内存生命周期,避免临时智能指针销毁对象:
void construct(std::vector<derivedA*>& da_vec) { // 直接new对象,不通过临时unique_ptr,后续需手动释放 da_vec.push_back(new derivedB(4)); } int main() { std::vector<derivedA*> da_vec; construct(da_vec); for (auto& da : da_vec) func(*da); // 手动释放所有对象,避免内存泄漏 for (auto da : da_vec) { delete da; } }
这种方法需要严格把控内存的创建与释放时机,容易因遗漏delete导致内存泄漏,或提前释放导致悬空指针,因此不推荐使用。
内容的提问来源于stack exchange,提问作者H'H
相关产品推荐
相关产品推荐

