I'm trying to create a function to copy a class that has pointer members, so the pointers are pointing at a copy rather than the original. There is one particular instance where I don't want changes to carry over to the original.
The problem comes when the destructor is called before the BoardState
object should be deleted. So when the Copy
function is called again, it is trying to delete the pointers and it can't because they were already deleted.
The strange thing is that if I remove the destructor, everything works. So I would think that if the object was destroyed, but the pointers weren't deleted then the allocated memory would be severed from the pointers and cause a memory leak. However, that is not what happens. The pointers still keep their values. So to me it seems that the destuctor is getting called without deleting the object.
I know I can use smart pointers and not worry about using a destructor, but I want to get a learning experience out of this. So I was hoping someone would be able to tell me what is happening.
Copy Function:
void BoardState::Copy(BoardState state)
{
copy = true;
if (p1 != nullptr) {
delete p1;
}
p1 = new Pawn(state.getP1());
if (p2 != nullptr) {
delete p2;
}
p2 = new Pawn(state.getP2());
if (walls != nullptr) {
delete walls;
}
walls = new list<Wall>(state.getWalls());
}
Destructor:
BoardState::~BoardState()
{
if (copy) {
if (p1 != nullptr) {
delete p1;
}
if (p2 != nullptr) {
delete p2;
}
if (walls != nullptr) {
delete walls;
}
}
}
At the end of this function, the destructor for SimulatedBoard
is called:
bool AI::startThinking(Pawn& pawn, Board& board)
{
simulatedBoard.Copy(board.getBoardState());
allPossibleDecision.clear();
plan.clear();
WallOptions.clear();
if (!thinking) {
thinking = true;
}
PathFinder pf(simulatedBoard);
list<sf::Vector2f> path = pf.createPath(board.getPawn(m_turnPos)->getPawn().getPosition(), sf::Vector2f(0, m_goal));
int opponent_turnPos = 1;
if (m_turnPos == 1) {
opponent_turnPos = 2;
}
int opponent_goal = 160;
if (m_goal == 160) {
opponent_goal = 640;
}
list<sf::Vector2f> opponent_path = pf.createPath(board.getPawn(opponent_turnPos)->getPawn().getPosition(), sf::Vector2f(0, opponent_goal));
int difference = opponent_path.size() - path.size();
int i;
if (difference < 0 && totalWalls > 0) {
i = 1;
}
else {
i = 2;
}
switch (i) {
case 1: {
list<decision>::iterator nextMove;
Wall placeWall;
bool foundBetterDifference = false;
addWallOptions(sf::Vector2f(190, 190),
simulatedBoard.getPawn(m_turnPos).getPawn().getPosition(),
simulatedBoard.getPawn(opponent_turnPos).getPawn().getPosition());
for (list<decision>::iterator it = allPossibleDecision.begin(); it != allPossibleDecision.end(); it++) {
decision d = (*it);
Wall w(d.wallPlacement, wallColor);
if (d.rotateWall) {
w.Rotate();
}
simulatedBoard.addWall(w);
opponent_path = pf.createPath(board.getPawn(opponent_turnPos)->getPawn().getPosition(), sf::Vector2f(0, opponent_goal));
path = pf.createPath(board.getPawn(m_turnPos)->getPawn().getPosition(), sf::Vector2f(0, m_goal));
simulatedBoard.removeWall(w);
int newDifference = opponent_path.size() - path.size();
if (newDifference > difference) {
foundBetterDifference = true;
difference = newDifference;
nextMove = it;
placeWall = w;
}
}
if (foundBetterDifference) {
board.addWall(placeWall);
plan.push_back(*nextMove);
totalWalls--;
break;
}
}
case 2 :
decision d;
d.movePawn = true;
d.pawnPos = path.front();
plan.push_back(d);
board.getPawn(m_turnPos)->getPawn().setPosition(path.front());
}
return false;
}
SimulatedBoard
is not created within this function. It is a member of the class. Even if the class goes out of scope and that is what is deleting the SimulatedBoard
, the next time the class is in scope again the constructor should run for SimulatedBoard
and set the pointers back to nullptr
. Unless my understanding is wrong, which it very well could be.
nullptr
before deleting.delete
works just fine with null pointers. – Pete BeckerBoardState
instead of aCopy
function. More than likely, you are passing or returningBoardState
by value somewhere, or making copies ofBoardState
. YourBoardState
lacks a user-defined copy constructor and assignment operator. Read up on the rule of 3 – PaulMcKenzienew / new[]
, a corresponding call todelete / delete[]
is executed. – PaulMcKenzie