C++中通过基类指针引用删除派生类对象触发段错误的解决方法
问题根源分析
这问题我熟,咱们一步步拆解为啥会触发这些错误:
- SIGSEGV(段错误)的原因:你在
ProcessAllCreatures里把CreatureList(i)返回的指针拷贝给了局部变量cr,当delete cr释放内存后,vector里存储的原始指针并没有被清空——它变成了野指针。下次循环遍历到这个位置时,你又会拿到这个野指针,访问cr->IsOnMap就是在访问已经被释放的内存,直接触发段错误。 - SIGABRT的原因:
&cr是栈上局部变量的地址,根本不是通过new分配的堆内存。delete只能用来释放堆上的动态内存,对栈地址执行delete属于未定义行为,系统直接抛出中止信号阻止你继续搞事情。
解决方案(无需修改vector类)
核心思路是:拿到vector里存储的指针的引用,在释放内存后把这个引用置为nullptr,这样后续循环就会通过if (!cr)跳过这个位置,不会再访问野指针。
修改后的ProcessAllCreatures函数如下:
void ProcessAllCreatures() { for (int i = 0; i < NextCreatureID; i++) { // 拿到vector中指针的引用,而不是副本 Creature*& cr = CreatureList(i); if (!cr) continue; if (!cr->IsOnMap) { delete cr; // 释放堆内存 cr = nullptr; // 关键:把vector里的指针置空,避免野指针 } } }
额外小建议(可选)
考虑到这是2006-2007年的老旧系统,虽然不能改vector类,但可以在Creature类里加一个IsDeleted布尔变量,在delete前标记状态,避免误操作。不过上面的方案已经足够解决当前问题,这个属于锦上添花的优化。
内容的提问来源于stack exchange,提问作者Svtyros
相关产品推荐
相关产品推荐

