Segmentation Fault in stepSimulation after removing Collision Object

Post Reply
ndanq
Posts: 2
Joined: Tue Feb 20, 2018 12:48 am

Segmentation Fault in stepSimulation after removing Collision Object

Post by ndanq »

Hey guys,

I'm trying to remove a collision object after a collision occurred. To do this in my collision callback, I add the object to a removal queue that addresses the removal of the collision object before calling stepSimulation. Is there something I am doing wrong with my remove code or approach?

Remove Function:

Code: Select all

void BulletPhysics::removeFromPhysicsWorld(STRigidBody *rigidBody) {
    for(int i = m_dynamicsWorld->getNumCollisionObjects() - 1; i>=0; i--){
        auto obj = m_dynamicsWorld->getCollisionObjectArray()[i];
        auto r = btRigidBody::upcast(obj);
        if(obj->getUserPointer() == ((BulletRigidBody*)rigidBody)->getRigidBody()->getUserPointer()){
            for(int j = (r->getNumConstraintRefs() - 1); j > 0; j--){
                m_dynamicsWorld->removeConstraint(r->getConstraintRef(j));
            }
            m_broadphase->getOverlappingPairCache()->cleanProxyFromPairs(r->getBroadphaseHandle(), m_dynamicsWorld->getDispatcher());
            if(r->getMotionState()){
                delete r->getMotionState();
            }
            m_dynamicsWorld->removeCollisionObject(obj);
            delete r->getCollisionShape();
            delete obj;
            return;
        }
    }
}
Update Function

Code: Select all

        for(auto rigidBody : m_removeQueue){
            removeFromPhysicsWorld(rigidBody);
        }
        m_removeQueue.clear();

        m_dynamicsWorld->stepSimulation(delta, 1, (1.0f / (stReal)STGame::Get()->getTargetFPS()));
       
 
User avatar
drleviathan
Posts: 849
Joined: Tue Sep 30, 2014 6:03 pm
Location: San Francisco

Re: Segmentation Fault in stepSimulation after removing Collision Object

Post by drleviathan »

I see two, maybe three, problems in your code:

(1) When you iterate over the constraint refs your loop exits at index = 0 rather than index = -1. As such, I believe you forget to remove the last constraint ref.

(2) You're calling btCollisionWorld::removeCollisionObject() rather than btDiscreteDynamicsWorld::removeRigidBody().

(3) This might be a memory leak depending on how you manage the BTRigidBody instances: you clear m_removeQueue before deleting the BTRigidBody pointers.

(4) Not a bug but an inefficiency: there is no need to loop over the bodies looking for a match if you already have the btRigidBody pointer via STRigidBody::getRigidBody(). In other words, I would expect the following code to work faster:

Code: Select all

void BulletPhysics::removeFromPhysicsWorld(STRigidBody *rigidBody) {
    // remove
    btRigidBody* r =rigidBody->getRigidBody();
    assert(r);
    for (int i = (r->getNumConstraintRefs() - 1); i >= 0; --i) {
        m_dynamicsWorld->removeConstraint(r->getConstraintRef(i));
    }
    m_dynamicsWorld->removeRigidBody(r);
   
    // delete        
    if (r->getMotionState()) {
        delete r->getMotionState();
    }       
    delete r->getCollisionShape();
    delete r;
}
ndanq
Posts: 2
Joined: Tue Feb 20, 2018 12:48 am

Re: Segmentation Fault in stepSimulation after removing Collision Object

Post by ndanq »

Sad to report, that didn't work. Removing the object did work, I declared a variable numCount to keep track of the number of collision objects. It does go down from 6 to 5 so the rigidbody/collision object is being removed. The error GDB detects it's calling "btRigidBody::saveKinematicState(float)", and the error message associated with it is "Calling Pure Virtual Method".

Update Loop:

Code: Select all

        
        int numCount = m_dynamicsWorld->getNumCollisionObjects();   //Keep Track Before Removal
        for(auto rigidBody : m_removeQueue){
            removeFromPhysicsWorld(rigidBody);
            delete rigidBody;
        }

        if(!m_removeQueue.empty()) {
            m_removeQueue.clear();
        }
        numCount = m_dynamicsWorld->getNumCollisionObjects(); //Amount after removal

        m_dynamicsWorld->stepSimulation(delta, 1, (1.0f / (stReal)STGame::Get()->getTargetFPS()));
Remove Function

Code: Select all

void BulletPhysics::removeFromPhysicsWorld(STRigidBody *rigidBody) {
    btRigidBody* r = dynamic_cast<BulletRigidBody*>(rigidBody)->getRigidBody();
    assert(r);
    for(int j = (r->getNumConstraintRefs() - 1); j >=0;  --j){
        m_dynamicsWorld->removeConstraint(r->getConstraintRef(j));
    }
    m_broadphase->getOverlappingPairCache()->cleanProxyFromPairs(r->getBroadphaseHandle(), m_dynamicsWorld->getDispatcher());
    m_dynamicsWorld->removeRigidBody(r);
}
BulletRigidBody Destructor

Code: Select all

BulletRigidBody::~BulletRigidBody() {
    if(m_rigidBody->getMotionState()){
        delete m_rigidBody->getMotionState();
    }
    delete m_rigidBody->getCollisionShape();
    delete m_rigidBody;
}
Post Reply