You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

如何解决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

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.07.20 13:45:01