GDB 断点不停止程序(Bullet Physics 库中的断点)

GDB breakpoint not stopping program (Breakpoint in Bullet Physics library)

我目前正在调试我编写的使用 Bullet Physics 的 C/C++ 程序。我正在开发 Ubuntu 14.04.3,使用 g++ 4.8.4、valgrind 3.10.1 和 Bullet Physics 2.82。

我的编译命令(用于调试)是:

   g++ -fno-inline -O0 -g -Wall -Wl,-rpath=./more_libs/lib,--enable-new-dtags -std=gnu++11 -I../bullet-2.82-r2704/Demos/OpenGL/ -I./more_libs/include/ -I../bullet-2.82-r2704/src/ ./main.cpp -L../bullet-2.82-r2704/Glut/ -L./more_libs/lib/ -L./more_libs/mesa -L../bullet-build/Demos/OpenGL/ -L../more_libs/lib/x86_64-linux-gnu -L../bullet-build/src/BulletDynamics/ -L../bullet-build/src/BulletCollision/ -L../bullet-build/src/LinearMath/ -lOpenGLSupport -lGL -lGLU -lglut -lBulletDynamics -lBulletCollision -lLinearMath -lXi -lXxf86vm -lX11 -o ./app

(调试和正常之间的区别在于 -O0 和 -fno-inline 选项。我正在添加库路径,因为我需要这个程序可以移植到我没有超级用户权限的集群.)

使用 Valgrind,我发现了大量类似的未初始化值错误,如下所示:

    Conditional jump or move depends on uninitialised value(s)
    at 0x4608C1: btSequentialImpulseConstraintSolver::solveGroupCacheFriendlySetup(btCollisionObject**, int, btPersistentManifold**, int, btTypedConstraint**, int, btContactSolverInfo const&, btIDebugDraw*) (in /home/josh/Documents/projects/evodevo_model/noise/EvoDevo-Modeling/evodevo/c++/app)
    by 0x4591FC: btSequentialImpulseConstraintSolver::solveGroup(btCollisionObject**, int, btPersistentManifold**, int, btTypedConstraint**, int, btContactSolverInfo const&, btIDebugDraw*, btDispatcher*) (in /home/josh/Documents/projects/evodevo_model/noise/EvoDevo-Modeling/evodevo/c++/app)
    by 0x46A3FF: btDiscreteDynamicsWorld::solveConstraints(btContactSolverInfo&) (in /home/josh/Documents/projects/evodevo_model/noise/EvoDevo-Modeling/evodevo/c++/app)
    by 0x467584: btDiscreteDynamicsWorld::internalSingleStepSimulation(float) (in /home/josh/Documents/projects/evodevo_model/noise/EvoDevo-Modeling/evodevo/c++/app)
    by 0x465459: btDiscreteDynamicsWorld::stepSimulation(float, int, float) (in /home/josh/Documents/projects/evodevo_model/noise/EvoDevo-Modeling/evodevo/c++/app)
    by 0x4088F4: NoiseWorld::clientMoveAndDisplay() (NoiseWorld.cpp:288)
    by 0x409A28: main (main.cpp:46)
    Uninitialised value was created by a heap allocation
    at 0x4C2ABBD: malloc (vg_replace_malloc.c:296)
    by 0x4EE043: btAlignedAllocDefault(unsigned long, int) (in /home/josh/Documents/projects/evodevo_model/noise/EvoDevo-Modeling/evodevo/c++/app)
    by 0x40BC09: btHingeConstraint::operator new(unsigned long) (btHingeConstraint.h:103)
    by 0x40CF73: NoiseWorld::CreateHinge(int, int, int, float, float, float, float, float, float, float, float, bool) (NoiseWorld.h:332)
    by 0x40807C: NoiseWorld::initPhysics() (NoiseWorld.cpp:193)
    by 0x4099F4: main (main.cpp:41)

我试图查看 solveGroupCacheFriendlySetup() 发生了什么,但是当我在那里设置断点和 运行 GDB 时,程序并没有停止——它只是 运行完成。我已经按函数和内存设置断点(在 valgrind 检查中保持不变),但是 none 其中 found/used.

那么,问题来了:在程序的 运行 期间,我如何查看 solveGroupCacheFriendlySetup() 中发生的事情?从那里,我想我将能够找出未初始化的内容。

如果这是一个简单的问题,请提前致歉,但过去两天我一直找不到答案。我是一个新手程序员,我已经接手了一个大项目,所以我猜我做错了一些简单的事情,但我现在不知道到底要问什么。

编辑: 根据 πìντα ῥεῖ 的建议,这是我在 运行ning 时需要查看的函数。可在此处找到此功能的在线文档:http://bulletphysics.org/Bullet/BulletFull/classbtSequentialImpulseConstraintSolver.html

注意:这部分代码不是我写的,我也不是 100% 了解它的作用。我很确定错误出在其他地方;我没有足够好地设置物理模拟器环境。

此外,我不知道 valgrind 消息“(in /home/josh/Documents/projects/evodevo_model/noise/EvoDevo-Modeling/evodevo/c++/app)”在尝试添加 GDB 在 运行ning 时可以找到的断点意味着什么程序。

btScalar btSequentialImpulseConstraintSolver::solveGroupCacheFriendlySetup(btCollisionObject** bodies, int numBodies, btPersistentManifold** manifoldPtr, int numManifolds,btTypedConstraint** constraints,int numConstraints,const btContactSolverInfo& infoGlobal,btIDebugDraw* debugDrawer)
{
    m_fixedBodyId = -1;
    BT_PROFILE("solveGroupCacheFriendlySetup");
    (void)debugDrawer;

    m_maxOverrideNumSolverIterations = 0;

#ifdef BT_ADDITIONAL_DEBUG
     //make sure that dynamic bodies exist for all (enabled) constraints
    for (int i=0;i<numConstraints;i++)
    {
        btTypedConstraint* constraint = constraints[i];
        if (constraint->isEnabled())
        {
            if (!constraint->getRigidBodyA().isStaticOrKinematicObject())
            {
                bool found=false;
                for (int b=0;b<numBodies;b++)
                {

                    if (&constraint->getRigidBodyA()==bodies[b])
                    {
                        found = true;
                        break;
                    }
                }
                btAssert(found);
            }
            if (!constraint->getRigidBodyB().isStaticOrKinematicObject())
            {
                bool found=false;
                for (int b=0;b<numBodies;b++)
                {
                    if (&constraint->getRigidBodyB()==bodies[b])
                    {
                        found = true;
                        break;
                    }
                }
                btAssert(found);
            }
        }
    }
    //make sure that dynamic bodies exist for all contact manifolds
    for (int i=0;i<numManifolds;i++)
    {
        if (!manifoldPtr[i]->getBody0()->isStaticOrKinematicObject())
        {
            bool found=false;
            for (int b=0;b<numBodies;b++)
            {

                if (manifoldPtr[i]->getBody0()==bodies[b])
                {
                    found = true;
                    break;
                }
            }
            btAssert(found);
        }
        if (!manifoldPtr[i]->getBody1()->isStaticOrKinematicObject())
        {
            bool found=false;
            for (int b=0;b<numBodies;b++)
            {
                if (manifoldPtr[i]->getBody1()==bodies[b])
                {
                    found = true;
                    break;
                }
            }
            btAssert(found);
        }
    }
#endif //BT_ADDITIONAL_DEBUG


    for (int i = 0; i < numBodies; i++)
    {
        bodies[i]->setCompanionId(-1);
    }


    m_tmpSolverBodyPool.reserve(numBodies+1);
    m_tmpSolverBodyPool.resize(0);

    //btSolverBody& fixedBody = m_tmpSolverBodyPool.expand();
    //initSolverBody(&fixedBody,0);

    //convert all bodies

    for (int i=0;i<numBodies;i++)
    {
        int bodyId = getOrInitSolverBody(*bodies[i],infoGlobal.m_timeStep);

        btRigidBody* body = btRigidBody::upcast(bodies[i]);
        if (body && body->getInvMass())
        {
            btSolverBody& solverBody = m_tmpSolverBodyPool[bodyId];
            btVector3 gyroForce (0,0,0);
            if (body->getFlags()&BT_ENABLE_GYROPSCOPIC_FORCE)
            {
                gyroForce = body->computeGyroscopicForce(infoGlobal.m_maxGyroscopicForce);
                solverBody.m_externalTorqueImpulse -= gyroForce*body->getInvInertiaTensorWorld()*infoGlobal.m_timeStep;
            }
        }
    }

    if (1)
    {
        int j;
        for (j=0;j<numConstraints;j++)
        {
            btTypedConstraint* constraint = constraints[j];
            constraint->buildJacobian();
            constraint->internalSetAppliedImpulse(0.0f);
        }
    }

    //btRigidBody* rb0=0,*rb1=0;

    //if (1)
    {
        {

            int totalNumRows = 0;
            int i;

            m_tmpConstraintSizesPool.resizeNoInitialize(numConstraints);
            //calculate the total number of contraint rows
            for (i=0;i<numConstraints;i++)
            {
                btTypedConstraint::btConstraintInfo1& info1 = m_tmpConstraintSizesPool[i];
                btJointFeedback* fb = constraints[i]->getJointFeedback();
                if (fb)
                {
                    fb->m_appliedForceBodyA.setZero();
                    fb->m_appliedTorqueBodyA.setZero();
                    fb->m_appliedForceBodyB.setZero();
                    fb->m_appliedTorqueBodyB.setZero();
                }

                if (constraints[i]->isEnabled())
                {
                }
                if (constraints[i]->isEnabled())
                {
                    constraints[i]->getInfo1(&info1);
                } else
                {
                    info1.m_numConstraintRows = 0;
                    info1.nub = 0;
                }
                totalNumRows += info1.m_numConstraintRows;
            }
            m_tmpSolverNonContactConstraintPool.resizeNoInitialize(totalNumRows);


            ///setup the btSolverConstraints
            int currentRow = 0;

            for (i=0;i<numConstraints;i++)
            {
                const btTypedConstraint::btConstraintInfo1& info1 = m_tmpConstraintSizesPool[i];

                if (info1.m_numConstraintRows)
                {
                    btAssert(currentRow<totalNumRows);

                    btSolverConstraint* currentConstraintRow = &m_tmpSolverNonContactConstraintPool[currentRow];
                    btTypedConstraint* constraint = constraints[i];
                    btRigidBody& rbA = constraint->getRigidBodyA();
                    btRigidBody& rbB = constraint->getRigidBodyB();

                    int solverBodyIdA = getOrInitSolverBody(rbA,infoGlobal.m_timeStep);
                    int solverBodyIdB = getOrInitSolverBody(rbB,infoGlobal.m_timeStep);

                    btSolverBody* bodyAPtr = &m_tmpSolverBodyPool[solverBodyIdA];
                    btSolverBody* bodyBPtr = &m_tmpSolverBodyPool[solverBodyIdB];




                    int overrideNumSolverIterations = constraint->getOverrideNumSolverIterations() > 0 ? constraint->getOverrideNumSolverIterations() : infoGlobal.m_numIterations;
                    if (overrideNumSolverIterations>m_maxOverrideNumSolverIterations)
                        m_maxOverrideNumSolverIterations = overrideNumSolverIterations;


                    int j;
                    for ( j=0;j<info1.m_numConstraintRows;j++)
                    {
                        memset(&currentConstraintRow[j],0,sizeof(btSolverConstraint));
                        currentConstraintRow[j].m_lowerLimit = -SIMD_INFINITY;
                        currentConstraintRow[j].m_upperLimit = SIMD_INFINITY;
                        currentConstraintRow[j].m_appliedImpulse = 0.f;
                        currentConstraintRow[j].m_appliedPushImpulse = 0.f;
                        currentConstraintRow[j].m_solverBodyIdA = solverBodyIdA;
                        currentConstraintRow[j].m_solverBodyIdB = solverBodyIdB;
                        currentConstraintRow[j].m_overrideNumSolverIterations = overrideNumSolverIterations;
                    }

                    bodyAPtr->internalGetDeltaLinearVelocity().setValue(0.f,0.f,0.f);
                    bodyAPtr->internalGetDeltaAngularVelocity().setValue(0.f,0.f,0.f);
                    bodyAPtr->internalGetPushVelocity().setValue(0.f,0.f,0.f);
                    bodyAPtr->internalGetTurnVelocity().setValue(0.f,0.f,0.f);
                    bodyBPtr->internalGetDeltaLinearVelocity().setValue(0.f,0.f,0.f);
                    bodyBPtr->internalGetDeltaAngularVelocity().setValue(0.f,0.f,0.f);
                    bodyBPtr->internalGetPushVelocity().setValue(0.f,0.f,0.f);
                    bodyBPtr->internalGetTurnVelocity().setValue(0.f,0.f,0.f);


                    btTypedConstraint::btConstraintInfo2 info2;
                    info2.fps = 1.f/infoGlobal.m_timeStep;
                    info2.erp = infoGlobal.m_erp;
                    info2.m_J1linearAxis = currentConstraintRow->m_contactNormal1;
                    info2.m_J1angularAxis = currentConstraintRow->m_relpos1CrossNormal;
                    info2.m_J2linearAxis = currentConstraintRow->m_contactNormal2;
                    info2.m_J2angularAxis = currentConstraintRow->m_relpos2CrossNormal;
                    info2.rowskip = sizeof(btSolverConstraint)/sizeof(btScalar);//check this
                    ///the size of btSolverConstraint needs be a multiple of btScalar
                    btAssert(info2.rowskip*sizeof(btScalar)== sizeof(btSolverConstraint));
                    info2.m_constraintError = &currentConstraintRow->m_rhs;
                    currentConstraintRow->m_cfm = infoGlobal.m_globalCfm;
                    info2.m_damping = infoGlobal.m_damping;
                    info2.cfm = &currentConstraintRow->m_cfm;
                    info2.m_lowerLimit = &currentConstraintRow->m_lowerLimit;
                    info2.m_upperLimit = &currentConstraintRow->m_upperLimit;
                    info2.m_numIterations = infoGlobal.m_numIterations;
                    constraints[i]->getInfo2(&info2);

                    ///finalize the constraint setup
                    for ( j=0;j<info1.m_numConstraintRows;j++)
                    {
                        btSolverConstraint& solverConstraint = currentConstraintRow[j];

                        if (solverConstraint.m_upperLimit>=constraints[i]->getBreakingImpulseThreshold())
                        {
                            solverConstraint.m_upperLimit = constraints[i]->getBreakingImpulseThreshold();
                        }

                        if (solverConstraint.m_lowerLimit<=-constraints[i]->getBreakingImpulseThreshold())
                        {
                            solverConstraint.m_lowerLimit = -constraints[i]->getBreakingImpulseThreshold();
                        }

                        solverConstraint.m_originalContactPoint = constraint;

                        {
                            const btVector3& ftorqueAxis1 = solverConstraint.m_relpos1CrossNormal;
                            solverConstraint.m_angularComponentA = constraint->getRigidBodyA().getInvInertiaTensorWorld()*ftorqueAxis1*constraint->getRigidBodyA().getAngularFactor();
                        }
                        {
                            const btVector3& ftorqueAxis2 = solverConstraint.m_relpos2CrossNormal;
                            solverConstraint.m_angularComponentB = constraint->getRigidBodyB().getInvInertiaTensorWorld()*ftorqueAxis2*constraint->getRigidBodyB().getAngularFactor();
                        }

                        {
                            btVector3 iMJlA = solverConstraint.m_contactNormal1*rbA.getInvMass();
                            btVector3 iMJaA = rbA.getInvInertiaTensorWorld()*solverConstraint.m_relpos1CrossNormal;
                            btVector3 iMJlB = solverConstraint.m_contactNormal2*rbB.getInvMass();//sign of normal?
                            btVector3 iMJaB = rbB.getInvInertiaTensorWorld()*solverConstraint.m_relpos2CrossNormal;

                            btScalar sum = iMJlA.dot(solverConstraint.m_contactNormal1);
                            sum += iMJaA.dot(solverConstraint.m_relpos1CrossNormal);
                            sum += iMJlB.dot(solverConstraint.m_contactNormal2);
                            sum += iMJaB.dot(solverConstraint.m_relpos2CrossNormal);
                            btScalar fsum = btFabs(sum);
                            btAssert(fsum > SIMD_EPSILON);
                            solverConstraint.m_jacDiagABInv = fsum>SIMD_EPSILON?btScalar(1.)/sum : 0.f;
                        }



                        {
                            btScalar rel_vel;
                            btVector3 externalForceImpulseA = bodyAPtr->m_originalBody ? bodyAPtr->m_externalForceImpulse : btVector3(0,0,0);
                            btVector3 externalTorqueImpulseA = bodyAPtr->m_originalBody ? bodyAPtr->m_externalTorqueImpulse : btVector3(0,0,0);

                            btVector3 externalForceImpulseB = bodyBPtr->m_originalBody ? bodyBPtr->m_externalForceImpulse : btVector3(0,0,0);
                            btVector3 externalTorqueImpulseB = bodyBPtr->m_originalBody ?bodyBPtr->m_externalTorqueImpulse : btVector3(0,0,0);

                            btScalar vel1Dotn = solverConstraint.m_contactNormal1.dot(rbA.getLinearVelocity()+externalForceImpulseA) 
                                                + solverConstraint.m_relpos1CrossNormal.dot(rbA.getAngularVelocity()+externalTorqueImpulseA);

                            btScalar vel2Dotn = solverConstraint.m_contactNormal2.dot(rbB.getLinearVelocity()+externalForceImpulseB) 
                                                                + solverConstraint.m_relpos2CrossNormal.dot(rbB.getAngularVelocity()+externalTorqueImpulseB);

                            rel_vel = vel1Dotn+vel2Dotn;
                            btScalar restitution = 0.f;
                            btScalar positionalError = solverConstraint.m_rhs;//already filled in by getConstraintInfo2
                            btScalar    velocityError = restitution - rel_vel * info2.m_damping;
                            btScalar    penetrationImpulse = positionalError*solverConstraint.m_jacDiagABInv;
                            btScalar    velocityImpulse = velocityError *solverConstraint.m_jacDiagABInv;
                            solverConstraint.m_rhs = penetrationImpulse+velocityImpulse;
                            solverConstraint.m_appliedImpulse = 0.f;


                        }
                    }
                }
                currentRow+=m_tmpConstraintSizesPool[i].m_numConstraintRows;
            }
        }

        convertContacts(manifoldPtr,numManifolds,infoGlobal);

    }

//  btContactSolverInfo info = infoGlobal;


    int numNonContactPool = m_tmpSolverNonContactConstraintPool.size();
    int numConstraintPool = m_tmpSolverContactConstraintPool.size();
    int numFrictionPool = m_tmpSolverContactFrictionConstraintPool.size();

    ///@todo: use stack allocator for such temporarily memory, same for solver bodies/constraints
    m_orderNonContactConstraintPool.resizeNoInitialize(numNonContactPool);
    if ((infoGlobal.m_solverMode & SOLVER_USE_2_FRICTION_DIRECTIONS))
        m_orderTmpConstraintPool.resizeNoInitialize(numConstraintPool*2);
    else
        m_orderTmpConstraintPool.resizeNoInitialize(numConstraintPool);

    m_orderFrictionConstraintPool.resizeNoInitialize(numFrictionPool);
    {
        int i;
        for (i=0;i<numNonContactPool;i++)
        {
            m_orderNonContactConstraintPool[i] = i;
        }
        for (i=0;i<numConstraintPool;i++)
        {
            m_orderTmpConstraintPool[i] = i;
        }
        for (i=0;i<numFrictionPool;i++)
        {
            m_orderFrictionConstraintPool[i] = i;
        }
    }

    return 0.f;

}

如果你想在 valgrind 下 运行 调试你的程序, 那么您可以执行以下操作:

valgrind --vgdb-error=1 .... 其余参数如常

然后在第一次出错时,valgrind 将停止,并等待 gdb 连接。 然后,您可以使用 gdb 命令 and/or valgrind 特定功能来 调查问题。您可以使用 gdb continue 继续执行 命令,在下一个错误时停止。

有关详细信息,请参阅 http://www.valgrind.org/docs/manual/manual-core-adv.html#manual-core-adv.gdbserver