2
votes

I am using box2d and have bodies that I am destroying out of the world time step (having marked them flagged them for removal) and yet the contact listener is still crashing due to getting contacts that are referencing these bodies.

This is what is done in the presolve and begin contact methods of the contact listener:

const b2Body* bodyA = contact->GetFixtureA()->GetBody();

const b2Body* bodyB = contact->GetFixtureB()->GetBody();

Object * objectA  = (Object*)bodyA->GetUserData();
Object * objectB  = (Object*)bodyB->GetUserData();

Either objectA or objectB are actually pointers to nonsense because the object has been removed (outside of the world time step). Appears that bad contacts are being created or contacts that should no longer exist still do.

Update

I have changed the code out of the world step to ensure and validate the correct bodies are being destroyed (as well their container's body) and find that the contact listener is still attempting to processing contacts that should not exist. I happen to be on iOS/Xcode and enable NSZombie and do indeed find the contact body userdata are deallocated objects (message sent to deallocated instance). Checking the Box2d source I find the contacts are indeed destroyed when the body is destroyed. I'll have to go through more Box2D code or just change my code to somehow work around these mysterious contacts the listener receives.

When I test setting the userdata for the body to null (again, outside the world step) the contacts that I receive in the contact listener for this body (when I check it in the contact listener) do not have null userdata.

2
How do you destroying the bodies? Show code, please. - Pavel
The bodies are destroyed in the proper way (world->DestroyBody(body);). I know the bodies are destroyed, the problem is that the old contacts do not appear to be removed on destroying the body, so these old contacts come through the contact listener and cause issues. - Skill M2
world->DestroyBody destroys all body contacts. Look there at its code: pastebin.com/cKJDfN6c (v2.2.1). I think, you are mix up smth (for example, destroying another body) - Pavel

2 Answers

1
votes

From what I see the destruction of the box2d body has nothing to do with all of that. GetUserData returns whatever you passed in when you created the body and that might be garbage. You eater deleted it or you passed in null. If you can provide the code for the creation and the destruction of the bodies I might be able to tell you bit more.

If the body would be invalid then the program would probably crash on:

contact->GetFixtureA()->GetBody();

or the bodyB part.

1
votes

The problem was I was creating two identical bodies, unbeknown to me, and passing them both the same userdata. When the first body was destroyed along with the corresponding user data (and containing object) the second one was still creating contact points and since the userdata associated with the body had been freed I was experiencing the problem described.

Setting NULL as the userdata for the body prior to deletion didn't appear to be working because when the crash occurred the debugger was actually showing me the second body which had not had it's user data set to NULL. The reason it took so long for me to find it was because the code had an inheritance structure within the container objects which made it difficult to spot that two bodies were being created.

This turned out to be an error that could not have been solved with just the code I posted so although the answers by Tomasz and Pavel did not lead me to solving the issue I must credit them with for taking the time to at least attempting to help. Thank you both.