C++异构集合从文件加载失败,运行时出现访问违规问题求助
问题分析与修复方案
你的代码出现运行时访问违规,主要是两个关键错误导致的:
1. switch语句中case 0缺少break
在HeterogeneousCollection::load的switch块里,处理case 0(Line类型)的代码块没有加break语句:
case 0: { Line* line = new Line; line->load(is); this->add(line); } // 这里没有break!
这意味着当加载完Line后,程序会继续执行case 1的代码——创建一个Circle并读取后续数据。这会导致两个严重问题:
- 集合里会被错误地添加一个额外的Circle对象
- Line的后续数据会被Circle的
load函数错误读取,彻底打乱整个输入流的读取顺序
2. id字段被重复读取
在保存数据时,HeterogeneousCollection::save先输出了Shape的id(os << (*this)[i].getId() << std::endl;),然后调用Shape::save又输出了一次id(os << id << std::endl;)。但加载时:
HeterogeneousCollection::load先读取了id(is >> id;)- 接着调用
Line::load/Circle::load,它们又会调用Shape::load,再次读取id(is >> id;)
这就导致每次加载时,都会跳过一个数据字段(原本应该是color的R值,却被当成id读走了),所有后续数据全部错位,最终加载的对象数据完全错误,访问时自然会出现内存违规。
修复后的代码
修复HeterogeneousCollection::load函数
添加case 0的break,避免执行后续case的代码:
void HeterogeneousCollection::load(std::istream& is) { is >> size; for (size_t i = 0; i<size; ++i) { int id; is >> id; switch (id) { case 0: { Line* line = new Line; line->load(is); this->add(line); break; // 新增break,终止当前case的执行 } case 1: { Circle* circle = new Circle; circle->load(is); this->add(circle); break; } default: break; } } }
修正Shape::load函数
移除重复读取id的语句,因为id已经在集合的load阶段处理过了:
void Shape::load(std::istream& is) { // 去掉这行重复读取的代码:is >> id; color.load(is); pos.load(is); }
同步Shape::save函数(可选但建议)
因为保存时集合已经输出了id,Shape::save里的id输出是冗余的,需要去掉以保证保存和加载逻辑一致:
void Shape::save(std::ostream& os) const { // 去掉这行冗余的id输出:os << id << std::endl; color.save(os); pos.save(os); }
如果不修改save函数,你需要手动调整现有保存文件,去掉每个Shape开头的重复id;如果用修正后的save重新生成文件,就能完全匹配修复后的load逻辑。
验证逻辑
修正后,加载流程会变成:
- 读取集合size
- 循环读取每个元素的id
- 根据id创建对应对象,调用其load函数(此时load只会读取color、pos以及子类的额外数据,不会重复读id)
- 每个case执行完后break,不会串到其他case
这样就能正确匹配你提供的文件内容,加载出正确的Line和Circle对象,避免内存访问违规。
内容的提问来源于stack exchange,提问作者Kabir
相关产品推荐
相关产品推荐

