简体   繁体   中英

Program Crash after displaying 2D array from queue

My C++ program consists of a class called States that has to hold a "state" of my puzzle which is a 3x3 int array and two other integers. When I declare them in main and print them, they print correctly with correct values, but after putting them into a priority_queue, sorted by one of the ints in the class, and pulling it back out, it has garbage in the array and crashes when it tries to display. I have no clue why it is getting garbage when I put it in and then pull back out, can anyone explain/help?

main.cpp:

#include "states.h"
#include <cstdlib>
#include <iostream>
#include <queue>

using namespace std;

int main(int argc, char *argv[])
{
priority_queue<States> statesQueue;
int puzzle[3][3];
for(int i=0; i<3; i++)
     for(int j=0; j<3; j++)
         puzzle[i][j] = i+j;

States myPuzzle(puzzle);
States myPuzzle2;

myPuzzle.printPuzzle();
myPuzzle2.printPuzzle();
myPuzzle.setFOfN(5);
myPuzzle2.setFOfN(0);

statesQueue.push(myPuzzle);
statesQueue.push(myPuzzle2);

if(statesQueue.empty()==true)
    cout<< "This is empty" <<endl;
else
    cout<< "This is not empty" <<endl;

statesQueue.top().printPuzzle();

system("PAUSE");
return EXIT_SUCCESS;
}

States.h:

#define STATES_H
#include <iostream>
using namespace std;

class States
{
public:

    States ();
    States (int puzzle[][3]);
    ~States();

    int getFOfN() const;
    void setFOfN(int num);

    int getGOfN() const;
    void setGOfN(int num);

    void incGOfN();
    int** getPuzzle() const;

    void printPuzzle() const;

    bool States::operator<(const States& rhs) const
    {
         return (fOfN < rhs.getFOfN());
    }
    States& operator = (const States& rhs)
    {
        for(int i=0; i<3; i++)
        {
            for(int j=0; j<3; j++)
            {    
                cout<< i << " " << j << " " << rhs.getPuzzle()[i][j] <<endl;
                puzzleGame[i][j] = rhs.getPuzzle()[i][j];
            }
        }
    }                         


private:
    int** puzzleGame;
    int gOfN;
    int fOfN;
};
#endif

States.cpp:

#include "states.h"
#include <iostream>

States::States ()
{
puzzleGame = new int*[3];

for (int i = 0; i<3; i++)
    puzzleGame[i] = new int[3];

puzzleGame[0][0] = 1;
puzzleGame[0][1] = 2;
puzzleGame[0][2] = 3;
puzzleGame[1][0] = 4;
puzzleGame[1][1] = 0;
puzzleGame[1][2] = 5;
puzzleGame[2][0] = 6;
puzzleGame[2][1] = 7;
puzzleGame[2][2] = 8;

}
//-------------------------------------------------------------------------
States::States (int puzzle[][3])
{
puzzleGame = new int*[3];

for (int i = 0; i<3; i++)
    puzzleGame[i] = new int[3];

for(int i=0; i<3; i++)
    for(int j=0; j<3; j++)
        puzzleGame[i][j] = puzzle[i][j];
}
//-------------------------------------------------------------------------
States::~States()
{
for (int i=0; i<3; i++)
{
    delete [] puzzleGame[i];
}
delete [] puzzleGame;
puzzleGame = 0;
}
//--------------------------------------------------------------------------      
int States::getFOfN() const
{

return fOfN;
}
//-------------------------------------------------------------------------
void States::setFOfN(int num)
{
 fOfN = num;
}
//--------------------------------------------------------------------------      
int States::getGOfN() const
{

return gOfN;
}
//-------------------------------------------------------------------------
void States::setGOfN(int num)
{
 gOfN = num;
}
//--------------------------------------------------------------------------      
void States::incGOfN()
{
 gOfN++;
}
//-------------------------------------------------------------------------
int** States::getPuzzle() const
{

return puzzleGame;
}
//-------------------------------------------------------------------------
void States::printPuzzle() const
{
std::cout<< "+---+---+---+" <<std::endl;
for(int i=0; i<3; i++)
{
    for(int j=0; j<3; j++)
    {
        if(puzzleGame[i][j]==0)
            std::cout<< "|   ";
        else
            std::cout<< "| " << puzzleGame[i][j] << " ";
    }
    std::cout<< "|" <<std::endl;
std::cout<< "+---+---+---+" <<std::endl;
}
}
//-------------------------------------------------------------------------

This is what happens everytime it displays: Picture

States violates the Rule of Three and cannot be safely copied. What is The Rule of Three? Glad you asked. Read the link.

In this case, copying States results in both the original and the copy pointing at the same puzzleGame When one is deleted it takes puzzleGame with it and the other is now a walking timebomb just waiting to invoke Undefined Behaviour.

This is a problem because pushing to a queue makes a copy, and that copy could be copied, moved, deleted or whatever else the queue's backing container decides to do to it.

The simple fix is to replace the dynamic puzzleGame array in States with a static one since the dimensions are known. std::array may be helpful here. Less suitable options include using a std::vector<std::vector<States>> and implementing assignment and move operators and copy and move constructors that correctly handle puzzleGame .

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM