如何解决C++代码中的HEAP CORRUPTION DETECTED错误?
面向对象C++程序堆损坏问题排查与修复
问题描述
编写了一个基于C++面向对象的基础程序,运行时出现堆损坏错误:HEAP CORRUPTION DETECTED: after Normal block (#159) at 0x000001F2C954FC30
不确定main函数末尾应该删除哪些对象,尝试多种删除方式后错误仍存在。
程序代码
#define _CRT_SECURE_NO_WARNINGS #include <iostream> using namespace std; class Plant { public: Plant(void); // Constructor for the Plant class Plant(const char*); // Overloaded constructor for the Plant class Plant(Plant&); // Copy constructor for the Plant class ~Plant(void) // Destructor for the Plant class { delete kingdom; } virtual void print(void); // Virtual function to print information about the Plant void link(Plant*); // Function to link a Plant object to the current object void printList(Plant*); // Function to print a list of Plant objects protected: char* kingdom; // Pointer to a character array representing the plant kingdom Plant* next; // Pointer to the next Plant object in the list }; class Flower : public Plant // Derived class Flower inheriting from the Plant class { public: Flower(const char* r = " division - Angiosperms"); // Constructor for the Flower class ~Flower(void) // Destructor for the Flower class { delete division; } virtual void print(void); // Virtual function to print information about the Flower private: char* division; // Pointer to a character array representing the flower division }; class ClassFlower : public Flower // Derived class ClassFlower inheriting from the Flower class { public: ClassFlower(const char* v = "Monocotyledons"); // Constructor for the ClassFlower class ~ClassFlower(void) // Destructor for the ClassFlower class { delete classFlower; } virtual void print(void); // Virtual function to print information about the ClassFlower private: char* classFlower; // Pointer to a character array representing the flower class }; // Definitions of class Plant member functions Plant::Plant(void) { next = 0; kingdom = new char[30]; strcpy(kingdom, " the most diverse kingdom of species"); } Plant::Plant(const char* newKingdom) { next = 0; kingdom = new char[strlen(newKingdom) + 1]; strcpy(kingdom, newKingdom); } Plant::Plant(Plant& newPlant) { next = 0; kingdom = new char[strlen(newPlant.kingdom) + 1]; strcpy(kingdom, newPlant.kingdom); } void Plant::print(void) { cout << "The plant kingdom is " << kingdom << "\n"; } void Plant::link(Plant* pt) { pt->next = next; next = pt; } void Plant::printList(Plant* first) { for (Plant* np = first; np; np = np->next) np->print(); } // Definitions of class Flower member functions Flower::Flower(const char* r) { division = new char[strlen(r) + 1]; strcpy(division, r); } void Flower::print(void) { cout << "Roses are from" << division << "\n"; } // Definitions of class ClassFlower member functions ClassFlower::ClassFlower(const char* r) { classFlower = new char[strlen(r) + 1]; strcpy(classFlower, r); } void ClassFlower::print(void) { Flower::print(); cout << "from class " << classFlower << "\n"; void getch(); } // main function void main(void) { Plant* p; Plant* p1; Plant* a = new Plant; // Create a Plant object using the default constructor Plant* u = new Flower; // Create a Flower object using the default constructor Plant* m = new ClassFlower; // Create a ClassFlower object using the default constructor p = a; Plant* list = p; p1 = u; p->link(p1); p = p1; p1 = m; p->link(p1); list->printList(list); // Print the list of Plant objects delete a; // Free the memory for the Plant object //delete u; // Free the memory for the Flower object //delete m; // Free the memory for the ClassFlower object delete p1; }
问题原因与修复方案
1. 基类析构函数未声明为虚函数(核心问题)
当用基类指针(Plant*)指向派生类对象(Flower/ClassFlower)并执行delete时,如果基类析构函数不是虚函数,编译器只会调用基类析构函数,不会触发派生类的析构逻辑。这会导致派生类中动态分配的内存(比如Flower的division、ClassFlower的classFlower)无法被释放,进而引发堆损坏。
修复:
将Plant类的析构函数声明为虚函数:
virtual ~Plant(void) { delete kingdom; }
2. 错误的内存释放操作
原代码中存在重复释放或释放逻辑混乱的问题:
p1最终指向m,执行delete p1等同于delete m,若同时保留注释的delete m会导致重复释放;- 未释放
u会造成内存泄漏,而错误的释放顺序或重复释放会触发堆损坏。
正确的释放方式:
所有用new创建的对象都需要单独delete,且确保每个对象只被释放一次。修改main函数末尾的释放代码:
delete a; delete u; delete m; // 无需再delete p1,因为p1指向的m已通过delete m释放
3. 其他次要问题修复
ClassFlower::print()中的void getch();是函数声明而非调用,改为getch();(如果需要暂停程序查看输出);- 遵循C++标准,将
void main(void)改为int main(),并在末尾添加return 0;。
修复后的完整main函数示例
int main() { Plant* p; Plant* p1; Plant* a = new Plant; Plant* u = new Flower; Plant* m = new ClassFlower; p = a; Plant* list = p; p1 = u; p->link(p1); p = p1; p1 = m; p->link(p1); list->printList(list); // 释放所有动态分配的对象 delete a; delete u; delete m; return 0; }
内容的提问来源于stack exchange,提问作者KrasimirMetev
相关产品推荐
相关产品推荐

