How to remove a player when dead without null pointer crash

Hi,
I have a method that check collisions between the player sprite and the enemies.

void CollisionSystem::runPlayerCollision(Vector<Sprite*>& enemies, Sprite* playerSprite)
{
    // I have a loop that checks the collisions and if a collisio is found it does this
    CCLOG("Collision found");
    playerSprite->removeFromParentAndCleanup(true);
    playerSprite->release();
}

My understanding is that removeFromParentAndCleanup doesn’t delete the pointer. So I add a release() to delete it.
Now this is what I don’t get. In the main update() loop of the game I added this

if (GameGlobals::playerSprite != nullptr)
{
     CCLOG("game running");
     collisionSystemInstance->runPlayerCollision(GameGlobals::enemies,  Game:Globals::player)
}

The output is

game running
game running
game running
game running
game running
"Collision found"

Exception thrown: read access violation.
playerSprite->**** was 0xDDDDDDDD.

So, the collision method is doing the work right because the games keeps running while the playerSprite exists. And when there is a collision, the LOG “Collision found” proves it is working ok, and therefor it deletes the playerSprite pointer. The error playerSprite->**** was 0xDDDDDDDD happens inside
collisionSystemInstance->runPlayerCollision(GameGlobals::enemies, Game:Globals::player), but why is it running that, if I stated to running only if the GameGlobals::playerSprite != nullptr??

The error means that playerSprite was delete right? which is what I want when it collides. But the condition to run the collision method is that the playerSprite exists, and it doesn’t, so why is it running it? I am confused.

R

That is not correct.

It’s crashing because you’re trying to free an object that has already been freed.

A call to release() needs to match a call to retain(). Assuming you’re just using the Sprite::createXXXX() methods, the sprite is set to auto-release, meaning it’s added to the auto-release pool which is checked every loop. When the sprite is removed from a node (via playerSprite->removeFromParentAndCleanup(true); or simply playerSprite->removeFromParent();, then its reference count reduces by 1. If the counter is 1, then given it is in the auto-release pool, it will be freed.

The only time you should be calling release() on it explicitly is if you called retain() on it, or created it with a new and never set it to be auto-released via a call to autorelease().

You, quite literally, have the source code right there in front of you. Using the debugger could have led you to the source of this issue very quickly. Perhaps it’s best you review the code related to the retain/release/autorelease functionality to get a better understanding of how it all works.

I ended up creating a global variable called gameIsStopped.So the update() loop only begins if it is fasle.
When a collision happens the variable is set to true, so update() won’t keep going. Not sure if this is the best way but I’ve seen similar workflows to pause the game, restart, etc…
Basically using global bool variables that are set depending on a specific condition. And those variables arre used in the main update() to perform diferente operations like game over, reducing lives, moving to next scene, etc… Seems alright to me.