I have this class ChessBoard, here’s its header:
class ChessBoard
{
Field** board;
Color currentColor;
public:
ChessBoard();
ChessBoard(const ChessBoard&);
Field* findField(std::string);
ChessBoard& operator = (const ChessBoard&);
bool checkIfFieldHasFigure(std::string);
void writeOneState(SahApi*);
void playAllMoves(std::istream*, SahApi*);
void playMove(std::string);
~ChessBoard();
};
And I have its constructor, which creates the beginning stage of chess board: (quite hideous, I know 🙂 )
ChessBoard::ChessBoard()
{
int i, j;
Error err;
board = new Field*[8];
if(!board)
{
err.writeToOutput(1);
exit(1);
}
for(i = 0; i < 8; i++)
{
board[i] = new Field[8];
if(!board[i])
{
err.writeToOutput(1);
exit(1);
}
}
currentColor = WHITE;
char c;
std::string s;
Figure f;
for(i = 0; i < 8; i++)
for(j = 0; j < 8; j++)
{
s.clear();
c = i + 'A';
s.push_back(c);
c = j + '1';
s.push_back(c);
board[i][j].position.assign(s);
if((j > 1) && (j < 6))
board[i][j].hasFigure = 0;
else board[i][j].hasFigure = 1;
if((i+j+2) % 2)
board[i][j].color = WHITE;
else board[i][j].color = BLACK;
if( ((j==0)||(j==7)) && ((i==0)||(i==7)) )
{
Rook* r = new Rook(((j==0)?WHITE:BLACK), s);
if(!r)
{
err.writeToOutput(1);
exit(1);
}
board[i][j].putFigure(r);
}
else if( ((i==1)||(i==6)) && ((j==0)||(j==7)) )
{
Knight* n = new Knight(((j==0)?WHITE:BLACK), s);
if(!n)
{
err.writeToOutput(1);
exit(1);
}
board[i][j].putFigure(n);
}
else if( ((i==2)||(i==5)) && ((j==0)||(j==7)) )
{
Bishop* b = new Bishop(((j==0)?WHITE:BLACK), s);
if(!b)
{
err.writeToOutput(1);
exit(1);
}
board[i][j].putFigure(b);
}
else if( (i==3) && ((j==0)||(j==7)))
{
Queen* q = new Queen(((j==0)?WHITE:BLACK), s);
if(!q)
{
err.writeToOutput(1);
exit(1);
}
board[i][j].putFigure(q);
}
else if( (i==4) && ((j==0)||(j==7)) )
{
King* k = new King(((j==0)?WHITE:BLACK), s);
if(!k)
{
err.writeToOutput(1);
exit(1);
}
board[i][j].putFigure(k);
}
else if( (j==1) || (j==6) )
{
Pawn* p = new Pawn(((j==1)?WHITE:BLACK), s);
if(!p)
{
err.writeToOutput(1);
exit(1);
}
board[i][j].putFigure(p);
}
}
}
I also need to have a destructor for ChessBoard, which is something like this:
ChessBoard::~ChessBoard()
{
//for(int i = 0; i < 8; i++)
// delete board[i];
delete [] board;
}
The reason part of it is commented out is my first question:
1. Why can’t I delete all my fields with the above written method? When I try to do it, the program goes into “Block type is valid” error, which I know is caused by trying to delete nonexistent memory. When I comment it out, the program works perfectly. And the ChessBoard is a matrix 8×8, so I should be able to delete it like I tried here.
My second question is:
2. How can I delete the pointers to Figures (King, Queen, Rook, …) which exist in my constructor for Chess Board? It’s confusing because those pointers are used as parts of my Chess Board, and I use them until the end of the program. When the program ends, I need to free my memory, but I don’t know how to access those pointers. The Figures themselves get auto-deleted because they are all non-pointers. Do I even need to delete those pointers, seeing as I use them until the end, and then everything is released?
The general rule for new/delete is that the calls have to match each other. You create your board with
You are going to need to delete your board the same way, but backwards:
Since this is not working I am guessing your issue is double deleting. Something else is freeing the array. Is it possible you have a copy of ChessBoard that is pointing to the same Field**?
You are going to have to delete your figures in a similar way.
This code will work as long as your code to remove a figure from the board deletes that figure and sets the position of that figure to NULL.
2b. The second part of your 2 question was whether you have to do any of this deleting at all, because the program is ending. You are right, in that you do not need to delete anything if you are going to quit right away anyways, the OS will release all that memory for you anyways.
You generally should though, usually you end up modifying most programs by allowing them to run multiple times, and then you will have a memory leak as each run uses slightly more memory.
That is how to solve your question as asked.
However, I would heavily suggest you to change the style of much of this code and remove all of the dynamic allocation.
First, use a regular static sized array (Field[8][8]) to store the field. I mean, when does a chess field ever change size?
Second, store pieces by value.Your field class already stores if a piece is in a location. Also have the Field class store an enum representing the type as well.
There is no reason to use dynamic allocation for your pieces.
Third, there is no need to check if the return of
newis NULL. If there is an error, it will throw an exception, and your program will stop(as it should, there is not much you can do when you are out of memory).