删除另一个类的类实例时堆损坏

时间:2009-08-04 14:59:48

标签: c++

(c ++ class issue)

这真的让我失望,当下面的类删除其成员指针(对于类播放器)的析构函数时,我得到一个'正常阻塞后的堆损坏'错误。

//Team.h
class Team
{
public:
    Team (const char* team_dir_path);
    ~Team(void);

    Team (const Team &team);

    Player* player;
    int player_cnt;
};

//Team.cpp

Team::Team( const char* team_dir_path )
{
    player = 0;
    player_cnt = 0;

    std::string* name;
    int* body;
    int* mind;
    int* speed;
    int* health;
    int* item;

    std::ifstream infile;
    infile.open( team_dir_path );
    if (infile.is_open())
    {
        infile >> player_cnt;

        if (player_cnt)
        {
            name = new std::string [player_cnt];
            body = new int [player_cnt];
            mind = new int [player_cnt];
            speed = new int [player_cnt];
            health = new int [player_cnt];
            item = new int [player_cnt];

            player = new Player[ player_cnt];


            for (int i=0; i<player_cnt; i++)
            {
                infile >> name[i] >> body[i] >> mind[i]
                       >> speed[i] >> health[i] >> item[i];
            }

            infile.close();

            for (int i=0; i<player_cnt; i++)

            {
                player[i].name = name[i];
                player[i].set_stat( BODY, body[i] );
                player[i].set_stat( MIND, mind[i] );
                player[i].set_stat( SPEED, speed[i] );
                player[i].set_stat( HEALTH, health[i] );
                player[i].set_stat( ITEM, item[i] );
            }

            delete [] name;
            delete [] body;
            delete [] mind;
            delete [] speed;
            delete [] health;
            delete [] item;
        }
    }
}

Team::~Team(void)
{
    if (player){ delete [] player;}
}

Team::Team (const Team &team)
{
    this -> player = new Player;
    this -> player_cnt = 0;
}

//Player.h
class Player
{
public:
    Player(void);
    ~Player(void);

    void set_stat (const int which, const int value){ stat[which] = value;}
    void assign_stat (const int which, const int value){ stat[which] += value;}
    int get_stat (const int which){ return stat[which];}

    std::string name;

private:    

    // BODY;MIND;SPEED;HEALTH;ITEM.

    int stat[ MAXSTAT ];
};

//Player.cpp
Player::Player(void)
{
}

Player::~Player(void)
{
}

// Main.cpp
int main()
{
    initscr();
    cbreak();
    noecho();  

    Team* team1 = 0;
    Team* team2 = 0;

    team1 = new Team("c:\\IB\\ib\\teams\\bombers.txt");
    team2 = new Team("c:\\IB\\ib\\teams\\maruaders.txt");

    refresh();
    napms(1000);

    if (team1){ delete team1;}
    if (team2){ delete team2;}

    endwin();
}

所以每当......

if (player){ delete [] player;}
在团队析构函数中达到了

我遇到了堆损坏错误。

请帮忙。

7 个答案:

答案 0 :(得分:14)

虽然C ++没有正式区分这些情况,但您需要将指向单个播放器的指针和一个指向一系列播放器的指针区分开来,因为它们不能以相同的方式删除。在您的代码中,您同时拥有:

player = new Player[ player_cnt];

其中玩家指向一个数组,这适合你的析构函数

delete [] player;

但也在你的ctor中:

this -> player = new Player;

使玩家指向单个玩家,从而使dtor中的delete []不正确。

答案 1 :(得分:2)

你做新玩家();并删除[]播放器

执行新的播放器[值]或删除播放器。

答案 2 :(得分:1)

从长远来看,这将有所帮助:

vector

另外,请考虑在堆栈上分配内存。你在这里有不必要的堆分配。

答案 3 :(得分:1)

你班上有一个RAW指针 这是个坏主意,因为使用RAW指针你必须正确定义以下方法:

Team::~Team()
{
    delete [] Player;
}

Team::Team()
{
    // Other stuff
    player = new Player[ player_cnt ];
    // Other stuff
}

Team::Team(Team const& copy)
{
    // Other stuff
    player = new Player[copy.player_cnt];
    // Other stuff
}

Team& operator=(Team const& copy)
{
    Team   tmp(copy);
    swap(tmp);
    return *this;
}

void swap(Team& s)
{
    std::swap(player,s.player);
    std::swap(player_cnt,s.player_cnt);
}

你可以看到它变得复杂。因此,将代码更改为使用std :: vector,所有这些问题都会消失。

此外,您的构造函数动态分配6个数组。如果这些请求中的任何一个失败,您最终会遇到一些令人讨厌的内存泄漏。您可以将代码粘贴在一个大的try {} catch {}块中,并确保在退出时始终取消分配内存。或者您可以使用std :: vector并且所有内容都已正确处理。

查看您的Player类。你有很多其他问题!
为什么要创建一个无效的对象,然后使用set_XXX()设置所有值。这看起来像Java一样令人讨厌。构造函数的重点在于您应该提供将对象正确初始化为VALID状态所需的所有参数。目前,在调用6个set_XXX()方法之前它无效。

另请注意,无需测试NULL指针。

if (player){ delete [] player;}

也改变这一点:

delete [] player;

为什么Team类处理玩家的阅读?
Player类应该读取自己的数据。团队应该阅读计数。创建所需数量的玩家,要求每个玩家从文件中读取自己的数据。

为什么不使用初始化列表来定义默认值。

Team::Team( const char* team_dir_path )
    :player(NULL)
    ,player_cnt(0)
{  /* Other stuff */ }

您不提供关闭定义:

BODY, MIND, SPEED, HEALTH, ITEM, MAXSTAT 

我打赌那里有一个错误。

答案 4 :(得分:0)

您的默认构造函数

新玩家;

而文件输入构造函数

new Player [num];

但是你的析构函数总是

删除[]播放器;

尝试修复它。

答案 5 :(得分:0)

编辑:似乎Alex Martelli找到了崩溃的原因,请参阅他对您实际问题的解决方案的答案。

这不直接回答您的问题,但大大简化了代码。代码越少,错误的空间越小:

Team::Team( const char* team_dir_path ) {  
    // NOTE: use RAII, it's just simpler        
    std::ifstream infile(team_dir_path);
    if (infile) {
        infile >> player_cnt;

        if (player_cnt) {
            // NOTE: would be better to use a std::vector!
            player = new Player[player_cnt];

            for (int i=0; i<player_cnt; i++) {
                std::string name;
                int body;
                int mind;
                int speed;
                int health;
                int item;

                // NOTE: would be better if a player knew how to read the stats itself, then you could just do: 
                // player[i].load(infile);
                infile >> name >> body >> mind >> speed >> health >> item;
                player[i].name = name;
                player[i].set_stat( BODY, body );
                player[i].set_stat( MIND, mind );
                player[i].set_stat( SPEED, speed );
                player[i].set_stat( HEALTH, health );
                player[i].set_stat( ITEM, item );
            }
        }
    }
}

答案 6 :(得分:0)

@Martin York

[QUOTE} 您不提供关闭定义: BODY,MIND,SPEED,HEALTH,ITEM,MAXSTATI打赌那里有错误 [/ QUOTE]

你是对的,这些值是在源文件中定义的,无法发布...

@Everyone

const int BODY = 1; const int MIND = 2; 等....

它们与数组'stat [MAXSTAT]'中的每个元素相关 所以我过度运行了stat数组,因为BODY应该是0, 心灵等等。

非常感谢堆积,是的,程序结构是缺乏的。

此外,我是否需要明确定义复制构造函数,运算符等 我正在使用类中的原始指针...即使我只创建2个实例 类团队将留到程序关闭,不需要复制分配???

。抱怨有关播放器=新播放器的复制构造函数错误, 这是一个错字。

非常乐意得到这个帮助。