C++ new分配指针内存泄漏且delete崩溃的修复方法
C++ 堆指针场景内存泄漏修复方案
现有代码核心问题
DoClone中new出的Dengue对象存入list返回时,确实不能在函数内提前delete——list只存储指针地址,不会拷贝堆上的实际对象,提前delete会直接让list内元素变成悬空指针,访问必然崩溃。但当前代码没有明确这些堆对象的释放责任主体,是内存泄漏的直接原因。DoDie的释放顺序完全错误:先把m_dna赋值为NULL,再delete空指针,根本没有释放m_dna原本指向的堆内存,直接造成泄漏;同时memset硬写长度4,如果m_protein是int等非1字节类型的数组,既无法完整清零数组,还存在内存操作风险。DoClone中对m_dna直接做指针浅拷贝,导致原对象、两个克隆对象三个指针指向同一块堆内存,只要任意一个对象释放这块内存,剩下两个对象持有的都是悬空指针,这也是你之前执行delete操作就崩溃的核心诱因。- 你用
Virus*基类指针存储Dengue派生类对象,如果Virus的析构函数不是虚函数,后续delete基类指针时不会调用派生类析构逻辑,同样会泄漏内存甚至崩溃。
具体修复步骤
1. 修正DoDie的释放逻辑
严格遵循「先释放指针指向的内存,再置空指针」的顺序,同时修正内存操作长度:
// 首先确保Virus类定义了虚析构函数 class Virus { public: virtual ~Virus() = default; // 加这行,保证派生类对象能被正确析构 // 其他原有成员... }; void DoDie() { // 先释放持有的堆内存 delete this->m_dna; // 释放完成再置空,避免悬空指针 this->m_dna = nullptr; // 用sizeof自动计算数组长度,不要硬编码数值 memset(this->m_protein, 0, sizeof(this->m_protein)); this->m_resistance = 0; }
2. 修复DoClone的浅拷贝问题
克隆新对象时,m_dna不能直接拷贝指针地址,要做深拷贝,保证每个对象持有独立的内存副本,避免重复释放:
list<Virus*> DoClone() { list<Virus*> l; Dengue *d1 = new Dengue(1), *d2 = new Dengue(1); for (int i = 0; i < 4; i++) d1->m_protein[i] = m_protein[i]; // m_dna做深拷贝,根据m_dna的实际类型选择实现: // 如果m_dna是自定义类型指针,直接调用拷贝构造生成新对象: // d1->m_dna = new DnaType(*m_dna); // 如果m_dna是C风格字符串: // d1->m_dna = new char[strlen(m_dna) + 1]; // strcpy(d1->m_dna, m_dna); d1->m_dna = DeepCopyDna(m_dna); // 替换为你实际业务的深拷贝逻辑 d1->m_resistance = m_resistance; for (int i = 0; i < 4; i++) d2->m_protein[i] = m_protein[i]; d2->m_dna = DeepCopyDna(m_dna); d2->m_resistance = m_resistance; l.emplace_back(d1); l.emplace_back(d2); return l; }
3. 明确内存释放责任
DoClone返回的list中存储的堆指针,释放责任由list的持有方承担,在list生命周期结束前必须遍历完成内存释放:
// 调用DoClone的业务代码示例 list<Virus*> cloneList = someVirus.DoClone(); // 执行业务逻辑... // 用完后必须逐元素释放 for (Virus* virusPtr : cloneList) { virusPtr->DoDie(); // 先释放对象内部持有的m_dna等堆内存 delete virusPtr; // 再释放Virus/Dengue对象本身 } cloneList.clear();
关键避坑点
- 不要在返回存储堆指针的容器前,在函数内释放指针,容器不会托管你手动new出来的堆内存。
- 类持有堆指针成员时,要么明确禁止拷贝/赋值(将拷贝构造、赋值运算符标记为
=delete),要么必须实现深拷贝逻辑,绝对不要默认浅拷贝导致多个指针指向同一块内存。 - 基类指针指向派生类对象的场景,基类必须声明虚析构函数,否则delete基类指针属于未定义行为。
内容的提问来源于stack exchange,提问作者Lưu Phạm Thị
相关产品推荐
相关产品推荐

