Changing body Velocity results in Segmentation Fault

Official forum for the Chipmunk2D Physics Library.
TurboLento
Posts: 11
Joined: Mon Feb 22, 2010 11:21 pm
Contact:

Changing body Velocity results in Segmentation Fault

Post by TurboLento »

First of all, the Chipmunk engine is fantastic, it's proving very stable and simple to use, I'm loving it so far. And the forum has been a great help.

I've been playing around with it a bit, and created a small demo in which I could add box objects (by dropping them from the top of the screen onto static "ground" segment). Added a lot of them, no problems at all.

While trying to mimic the "Player" demo, creating a ball that moves by changing it's velocity, over the code where I add box objects, I get occasional crashes, sometimes when I move and collide with some box objects, and occasionally occurring without any collisions existing. The debugger indicates a crash at the line where I change the velocity,

body->v.x = -10.0f;

with a SIGSEV. Placing "assert(body)" right before it doesn't trigger.

I've attempted to compile Chipmunk as a static and dynamic library, and to compile it directly into my code, and results are the same.
It all seems to be related to the movement, because if I disabled the movement and add boxes, while leaving the circle on the scene, it doesn't crash.

Some extra data: I'm using Allegro as a rendering/input library, programming in Code::Blocks using the MingW compiler. Using Chipmunk 5.1.

Any ideas?
ShiftZ
Posts: 114
Joined: Sat Mar 07, 2009 7:23 am
Contact:

Re: Changing body Velocity results in Segmentation Fault

Post by ShiftZ »

Placing "assert(body)" right before it doesn't trigger.
It doesn't trigger on invalid body pointer. Is there any body removing operation in your code?
User avatar
Tam Toucan
Posts: 141
Joined: Tue Jun 23, 2009 4:26 pm
Contact:

Re: Changing body Velocity results in Segmentation Fault

Post by Tam Toucan »

As ShiftZ says the assert only triggers if the condition is false i.e. if the pointer is NULL it would trigger (it's not a smart macro it just checks true/false).

So you either have a corrupt body pointer, or you have removed the body. Post code samples (use the code tags, sorry personal bugbear ;)) of how you create and remove your objects.
TurboLento
Posts: 11
Joined: Mon Feb 22, 2010 11:21 pm
Contact:

Re: Changing body Velocity results in Segmentation Fault

Post by TurboLento »

Thanks for the replies.

I'm not doing any body or shape removal at any times.

Physics initialization code:

Code: Select all

void physicsInitialize(void)
{
    cpInitChipmunk();

	// Initialize a static body with infinite mass and moment of inertia
	// to attach the static geometry to.
	staticBody = cpBodyNew(INFINITY, INFINITY);

	// Optional. Read the docs to see what this really does.
	//cpResetShapeIdCounter();

	// Create a space and adjust some of it's parameters.
	space = cpSpaceNew();
	// Lets set some parameters of the space:
	// More iterations make the simulation more accurate but slower
	space->iterations = 10;
	// These parameters tune the efficiency of the collision detection.
	// For more info: http://code.google.com/p/chipmunk-physics/wiki/cpSpace
	cpSpaceResizeStaticHash(space, 30.0f, 1000);
	cpSpaceResizeActiveHash(space, 30.0f, 1000);
	// Give it some gravity
	space->gravity = cpv(0, 90);

	cpShape *shape;

    Vector2 screenDimensions = Graphics::getPtr()->getScreenDimensions();

	// Create some segments around the edges of the screen.
	shape = cpSegmentShapeNew(staticBody, cpv(0,0), cpv(0,screenDimensions.y), 0.0f);
	shape->e = 1.0; shape->u = 1.0;
	cpSpaceAddStaticShape(space, shape);

	shape = cpSegmentShapeNew(staticBody, cpv(0,screenDimensions.y), cpv(screenDimensions.x,screenDimensions.y), 0.0f);
	shape->e = 1.0; shape->u = 1.0;
	cpSpaceAddStaticShape(space, shape);

	shape = cpSegmentShapeNew(staticBody,cpv(screenDimensions.x,screenDimensions.y), cpv(0,screenDimensions.y), 0.0f);
	shape->e = 1.0; shape->u = 1.0;
	cpSpaceAddStaticShape(space, shape);

	// add player
	Vector2 playerPos(200,200), playerSize(15,15);
	//addObjectBox("player1", playerPos, playerSize, 0, false);
	addObjectCircle("player1", playerPos, playerSize.x, false);
}
addObjectCircle (circle initialization code):

Code: Select all

void addObjectCircle(std::string name, Vector2 pos, float radius, bool isStatic)
{
	Object newObject;
	newObject.name = name;

	// Set up the player
	newObject.physBody = cpSpaceAddBody(space, cpBodyNew(1.0f, INFINITY));
	//newObject.physBody = cpSpaceAddBody(space, cpBodyNew(1.0f, cpMomentForCircle(1.0f, 0, radius, cpvzero)));
	newObject.physBody->p = cpv(pos.x, pos.y);
	//newObject.physBody->velocity_func = playerUpdateVelocity;

	newObject.physShape = cpSpaceAddShape(space, cpCircleShapeNew(newObject.physBody, radius, cpvzero));
	newObject.physShape->e = 0.0f;
	newObject.physShape->u = 1.0f;
	//newObject.physShape->collision_type = 1;

	objectList.push_back(newObject);
}
Box creation code:

Code: Select all

void addObjectBox(std::string objectName, Vector2 pos, Vector2 dimensions, float angleRadians, bool isStatic)
{
    Object newObject;
    newObject.name = objectName;

	std::vector<cpVect> verticesList = getVerticesForBox(dimensions);

	// Create a box and initialize some of its parameters.
	newObject.physBody = createBodyWithParameters(verticesList, pos);
	cpSpaceAddBody(space, newObject.physBody);

	newObject.physShape = createShapePolyWithParameters(verticesList, Vector2(0,0), newObject.physBody);
	cpSpaceAddShape(space, newObject.physShape);

	// Add a collision callback between objects of the default type and the box.
	//cpSpaceAddCollisionPairFunc(space, 1, 0, &collFunc, &some_value);

	cpBodySetAngle(newObject.physBody, angleRadians);

	// add Object to object list
	objectList.push_back(newObject);
}

std::vector<cpVect> getVerticesForBox(Vector2 dimensions)
{
    return getVerticesForBox(dimensions, Vector2(0,0));
}

std::vector<cpVect> getVerticesForBox(Vector2 dimensions, Vector2 offset)
{
        std::vector<cpVect> verticesList;
	verticesList.push_back(cpv((-dimensions.x * 0.5f) + offset.x, (-dimensions.y * 0.5f)+ offset.y));
        verticesList.push_back(cpv((-dimensions.x * 0.5f) + offset.x, (dimensions.y * 0.5f) + offset.y));
        verticesList.push_back(cpv((dimensions.x * 0.5f) + offset.x, (dimensions.y * 0.5f) + offset.y));
        verticesList.push_back(cpv((dimensions.x * 0.5f) + offset.x, (-dimensions.y * 0.5f) + offset.y ));
        return verticesList;
}

cpBody* createBodyWithParameters(std::vector<cpVect>& verticesList, Vector2 pos)
{
        cpVect* verts = (cpVect*) malloc(sizeof(cpVect) * verticesList.size());
        for(unsigned int idxVect = 0; idxVect < verticesList.size(); ++idxVect)
                verts[idxVect] = verticesList[idxVect];

        cpBody* physBody = cpBodyNew(1.0, cpMomentForPoly(1.0, verticesList.size(), verts, cpvzero));
        //cpBody* physBody = cpBodyNew(INFINITY, INFINITY);
	physBody->p = cpv(pos.x, pos.y);
	return physBody;
}

cpShape* createShapePolyWithParameters(std::vector<cpVect>& verticesList, Vector2 pos, cpBody* bodyToAddTo)
{
        cpVect* verts = (cpVect*) malloc(sizeof(cpVect) * verticesList.size());
        for(unsigned int idxVect = 0; idxVect < verticesList.size(); ++idxVect)
                verts[idxVect] = verticesList[idxVect];
        //cpShape* physShape = cpPolyShapeNew(bodyToAddTo, verticesList.size(), verts, cpvzero);
        cpShape* physShape = cpPolyShapeNew(bodyToAddTo, verticesList.size(), verts, cpv(pos.x, pos.y));
	physShape->e = 0.0;
	physShape->u = 1.5;
	physShape->collision_type = 1;
	return physShape;
}
Object struct:

Code: Select all

typedef struct Object
{
    std::string name;
    cpBody* physBody;
    cpShape *physShape;
    Vector2 shapeOffset;    // offset of the shape relative to the body
};
So you either have a corrupt body pointer, or you have removed the body.
How would a body pointer corruption occur, and why in such specific circumstances?
ShiftZ
Posts: 114
Joined: Sat Mar 07, 2009 7:23 am
Contact:

Re: Changing body Velocity results in Segmentation Fault

Post by ShiftZ »

How would a body pointer corruption occur
Show please objectList definition and place where you assigning velocity.
TurboLento
Posts: 11
Joined: Mon Feb 22, 2010 11:21 pm
Contact:

Re: Changing body Velocity results in Segmentation Fault

Post by TurboLento »

EDIT: ok, the corruption is actually happening with the "body" pointer. I've printed the pointer address at every cycle, and just before the error it changes to another value. Time for more bug tracing :)


Oh sorry, forgot to include it.
"objectList" is a std::vector of Object, defined globally.

body->v.x is being changed in my main cycle (the "while" cycle below), which resides in my main() function, and is posted below:

Code: Select all

int main(void)
{
    try
    {

    graphicsInitialize();
    physicsInitialize();

    std::cout << "Hit + to add object\n";

    clear_keybuf(); // clear any previous keyboard input

    bool cmdExit = false;
    bool cmdAddObject = false;

    Object* player = getObjectByName("player1");

    while(!cmdExit)
    {
        if(key[KEY_ESC])
            cmdExit = true;

        if(key[KEY_PLUS_PAD])
            cmdAddObject = true;
        else
        {
            if(cmdAddObject)
            {
                Vector2 pos(320,10);
                Vector2 dimensions(20,10);
                addObjectBox(pos, dimensions, 0, false);
                cmdAddObject = false;
            }
        }

        // player controls
        if(key[KEY_LEFT])
        {
            assert(player);
            assert(player->physBody);
            player->physBody->v.x = -10.0f; // crash happens either here or below
            //cpBodyApplyImpulse(player->physBody, cpv(-10.0f,0), cpvzero);
        }
        if(key[KEY_RIGHT])
        {
            assert(player);
            assert(player->physBody);
            player->physBody->v.x = 10.0f; // crash also happens here
            //cpBodyApplyImpulse(player->physBody, cpv(10.0f,0), cpvzero);
        }

        physicsUpdate(1);
        graphicsUpdate();
        //rest(100);
    }

    physicsTerminate();
    graphicsTerminate();

    }
    catch (...) {                       // catch an error
        std::cout << "Caught an exception -- value is: ";
        //std::cout << i << "\n";
    }

    return 0;

}
END_OF_MAIN()
P.S.: END_OF_MAIN is required by allegro.

Below, i post my whole program's code, excluding code for libraries (I think the libraries function calls are self explanatory).

Code: Select all

#include <iostream>
#include <vector>
#include <allegro.h>
#include "chipmunk.h"
#include "Graphics/Graphics.h"
#include "Vector/Vector2.h"
#include "Math/Math.h"
#include <cmath>

cpSpace *space;
cpBody *staticBody;
//cpBody *body;


typedef struct Object
{
    std::string name;
    cpBody* physBody;
    cpShape *physShape;
    Vector2 shapeOffset;    // offset of the shape relative to the body
};

std::vector<Object> objectList;



int some_value = 42;

bool graphicsInitialize();
void graphicsUpdate();
bool graphicsTerminate();

void physicsInitialize(void);
void physicsUpdate(int ticks);
static int collFunc(
    cpShape *a, cpShape *b, cpContact *contacts, int numContacts,
    cpFloat normal_coef, void *data);
void physicsTerminate(void);

void addObjectBox(Vector2 pos, Vector2 dimensions, float angleRadians, bool isStatic);
void addObjectBox(std::string objectName, Vector2 pos, Vector2 dimensions, float angleRadians, bool isStatic);
void addObjectCircle(std::string name, Vector2 pos, float radius, bool isStatic);

std::vector<cpVect> getVerticesForBox(Vector2 dimensions);
std::vector<cpVect> getVerticesForBox(Vector2 dimensions, Vector2 offset);

//cpBody* createBodyWithParameters(cpVect* verticesList, unsigned int verticesTotal, Vector2 pos);       // creates a body with these vertices and pos, but doesn't add it to the space
//cpShape* createShapePolyWithParameters(cpVect* verticesList, unsigned int verticesTotal, Vector2 pos, Vector2 size, cpBody* bodyToAddTo);
cpBody* createBodyWithParameters(std::vector<cpVect>& verticesList, Vector2 pos);
cpShape* createShapePolyWithParameters(std::vector<cpVect>& verticesList, Vector2 pos, cpBody* bodyToAddTo);

Object* getObjectByName(std::string objectName);
bool getObjectIndexByName(std::string objectName, unsigned int& idxObjectFound);
void deleteObjectByName(std::string objectName);


////////////////////////////////
// Main ////////////////////////
////////////////////////////////

int main(void)
{
    try
    {

    graphicsInitialize();
    physicsInitialize();

    std::cout << "Hit + to add object\n";

    clear_keybuf();

    bool cmdExit = false;
    bool cmdAddObject = false;

    Object* player = getObjectByName("player1");

    while(!cmdExit)
    {
        if(key[KEY_ESC])
            cmdExit = true;

        if(key[KEY_PLUS_PAD])
            cmdAddObject = true;
        else
        {
            if(cmdAddObject)
            {
                Vector2 pos(320,10);
                Vector2 dimensions(20,10);
                addObjectBox(pos, dimensions, 0, false);
                cmdAddObject = false;
            }
        }

        // player controls
        if(key[KEY_LEFT])
        {
            assert(player);
            assert(player->physBody);
            player->physBody->v.x = -10.0f;
            //cpBodyApplyImpulse(player->physBody, cpv(-10.0f,0), cpvzero);
        }
        if(key[KEY_RIGHT])
        {
            assert(player);
            assert(player->physBody);
            player->physBody->v.x = 10.0f;
            //cpBodyApplyImpulse(player->physBody, cpv(10.0f,0), cpvzero);
        }

        physicsUpdate(1);
        graphicsUpdate();
        //rest(100);
    }

    physicsTerminate();
    graphicsTerminate();

    }
    catch (...) {                       // catch an error
        std::cout << "Caught an exception -- value is: ";
        //std::cout << i << "\n";
    }

    return 0;

}
END_OF_MAIN()


bool graphicsInitialize()
{
    if(system_driver == NULL) // to ensure allegro is only initialed once - http://www.allegro.cc/forums/thread/591306/670840#target
    {
        allegro_init();
        install_timer();
        install_keyboard();
    }

    Graphics::create(640,480,16);
}

void graphicsUpdate()
{
    for(unsigned int idxObject = 0; idxObject < objectList.size(); ++idxObject)
    {
        cpBody* body = objectList[idxObject].physBody;
        //std::cout << "body "<< idxObject <<" pos:" << body->p.x <<","<< body->p.y << "\n";

        cpShape* shape = objectList[idxObject].physShape;
        if(shape == 0)
            continue;
        //std::cout << "AAAA\n";
        assert(shape);

        // draw to screen
        switch(shape->klass->type)
        {
            case CP_CIRCLE_SHAPE:
            {
                float radius = cpCircleShapeGetRadius(shape);
                Vector2 pos(body->p.x, body->p.y);
                Graphics::getPtr()->drawCircle(pos,radius,Graphics::getPtr()->getColor(Graphics::Colors::Blue));
            }
            break;
            case CP_SEGMENT_SHAPE:
            break;
            case CP_POLY_SHAPE:
            {
                Vector2 shapeOffset = objectList[idxObject].shapeOffset;
                Vector2 bodyCenter(body->p.x, body->p.y);

                cpVect topVect = cpPolyShapeGetVert(shape, 0);
                cpVect bottomVect = cpPolyShapeGetVert(shape, 2);

                Vector2 halfDims((bottomVect.x - topVect.x) * 0.5f, (bottomVect.y - topVect.y) * 0.5f),
                        //pos(body->p.x, body->p.y);
                        pos(shapeOffset.x, shapeOffset.y);
                //shapeOffset = Vector2();
                float angleRads = body->a;
                //Graphics::getPtr()->drawAABB(pos,halfDims,Graphics::getPtr()->getColor(Graphics::Colors::Blue));
                //Graphics::getPtr()->drawOBB(pos,halfDims,angleRads,Graphics::getPtr()->getColor(Graphics::Colors::Blue));

                Graphics::getPtr()->drawOBB(pos,halfDims,bodyCenter,angleRads,Graphics::getPtr()->getColor(Graphics::Colors::Blue));
            }
            break;
        }
    }

    //std::cout << "done drawin\n";
    Graphics::getPtr()->drawToScreen();
}

bool graphicsTerminate()
{
    Graphics::destroy();
    allegro_exit();
}

void physicsInitialize(void)
{
    cpInitChipmunk();

	// Initialize a static body with infinite mass and moment of inertia
	// to attach the static geometry to.
	staticBody = cpBodyNew(INFINITY, INFINITY);

	// Optional. Read the docs to see what this really does.
	//cpResetShapeIdCounter();

	// Create a space and adjust some of it's parameters.
	space = cpSpaceNew();
	// Lets set some parameters of the space:
	// More iterations make the simulation more accurate but slower
	space->iterations = 10;
	// These parameters tune the efficiency of the collision detection.
	// For more info: http://code.google.com/p/chipmunk-physics/wiki/cpSpace
	cpSpaceResizeStaticHash(space, 30.0f, 1000);
	cpSpaceResizeActiveHash(space, 30.0f, 1000);
	// Give it some gravity
	space->gravity = cpv(0, 90);

	cpShape *shape;

    Vector2 screenDimensions = Graphics::getPtr()->getScreenDimensions();

	// Create some segments around the edges of the screen.
	shape = cpSegmentShapeNew(staticBody, cpv(0,0), cpv(0,screenDimensions.y), 0.0f);
	shape->e = 1.0; shape->u = 1.0;
	cpSpaceAddStaticShape(space, shape);

	shape = cpSegmentShapeNew(staticBody, cpv(0,screenDimensions.y), cpv(screenDimensions.x,screenDimensions.y), 0.0f);
	shape->e = 1.0; shape->u = 1.0;
	cpSpaceAddStaticShape(space, shape);

	shape = cpSegmentShapeNew(staticBody,cpv(screenDimensions.x,screenDimensions.y), cpv(0,screenDimensions.y), 0.0f);
	shape->e = 1.0; shape->u = 1.0;
	cpSpaceAddStaticShape(space, shape);

    // add player
    Vector2 playerPos(200,200), playerSize(15,15);
    //addObjectBox("player1", playerPos, playerSize * 2, 0, false); // setting the player as a box crashes as well
    addObjectCircle("player1", playerPos, playerSize.x, false);
}

void physicsUpdate(int ticks)
{
	int steps = 3;  // divide velocity by this value
	cpFloat dt = 1.0/60.0/(cpFloat)steps;

	int i;
	//for(int i=0; i<steps; i++){
	for(i=0; i<steps; i++)
	{
		cpSpaceStep(space, dt);
	}

	// or:
	//cpSpaceStep(space, 1.0f/60.0f);
}

void addObjectBox(Vector2 pos, Vector2 dimensions, float angleRadians, bool isStatic)
{
    addObjectBox("", pos, dimensions, angleRadians, isStatic);
}

void addObjectBox(std::string objectName, Vector2 pos, Vector2 dimensions, float angleRadians, bool isStatic)
{
    Object newObject;
    newObject.name = objectName;

	std::vector<cpVect> verticesList = getVerticesForBox(dimensions);

	// Create a box and initialize some of its parameters.
	//newObject.physBody = cpBodyNew(1.0, cpMomentForPoly(1.0, num, verts, cpvzero));
	//newObject.physBody->p = cpv(pos.x, pos.y);
	newObject.physBody = createBodyWithParameters(verticesList, pos);
	cpSpaceAddBody(space, newObject.physBody);

	//newObject.physShape = cpPolyShapeNew(newObject.physBody, num, verts, cpvzero);
	//newObject.physShape->e = 0.0; newObject.physShape->u = 1.5;
	//newObject.physShape->collision_type = 1;
	newObject.physShape = createShapePolyWithParameters(verticesList, Vector2(0,0), newObject.physBody);
	cpSpaceAddShape(space, newObject.physShape);

	// Add a collision callback between objects of the default type and the box.
	//cpSpaceAddCollisionPairFunc(space, 1, 0, &collFunc, &some_value);

	cpBodySetAngle(newObject.physBody, angleRadians);

	// add Object to object list
	objectList.push_back(newObject);
}

void addObjectCircle(std::string name, Vector2 pos, float radius, bool isStatic)
{
    Object newObject;
    newObject.name = name;

    // Set up the player
	newObject.physBody = cpSpaceAddBody(space, cpBodyNew(1.0f, INFINITY));
	//newObject.physBody = cpSpaceAddBody(space, cpBodyNew(1.0f, cpMomentForCircle(1.0f, 0, radius, cpvzero)));
	newObject.physBody->p = cpv(pos.x, pos.y);
	//newObject.physBody->velocity_func = playerUpdateVelocity;

	newObject.physShape = cpSpaceAddShape(space, cpCircleShapeNew(newObject.physBody, radius, cpvzero));
	newObject.physShape->e = 0.0f;
	newObject.physShape->u = 1.0f;
	//newObject.physShape->collision_type = 1;

	objectList.push_back(newObject);
}

std::vector<cpVect> getVerticesForBox(Vector2 dimensions)
{
    return getVerticesForBox(dimensions, Vector2(0,0));
}

std::vector<cpVect> getVerticesForBox(Vector2 dimensions, Vector2 offset)
{
    std::vector<cpVect> verticesList;
	verticesList.push_back(cpv((-dimensions.x * 0.5f) + offset.x, (-dimensions.y * 0.5f)+ offset.y));
    verticesList.push_back(cpv((-dimensions.x * 0.5f) + offset.x, (dimensions.y * 0.5f) + offset.y));
    verticesList.push_back(cpv((dimensions.x * 0.5f) + offset.x, (dimensions.y * 0.5f) + offset.y));
    verticesList.push_back(cpv((dimensions.x * 0.5f) + offset.x, (-dimensions.y * 0.5f) + offset.y ));
    return verticesList;
}

cpBody* createBodyWithParameters(std::vector<cpVect>& verticesList, Vector2 pos)
{
    cpVect* verts = (cpVect*) malloc(sizeof(cpVect) * verticesList.size());
    for(unsigned int idxVect = 0; idxVect < verticesList.size(); ++idxVect)
        verts[idxVect] = verticesList[idxVect];

    cpBody* physBody = cpBodyNew(1.0, cpMomentForPoly(1.0, verticesList.size(), verts, cpvzero));
    //cpBody* physBody = cpBodyNew(INFINITY, INFINITY);
	physBody->p = cpv(pos.x, pos.y);
	return physBody;
}

cpShape* createShapePolyWithParameters(std::vector<cpVect>& verticesList, Vector2 pos, cpBody* bodyToAddTo)
{
    cpVect* verts = (cpVect*) malloc(sizeof(cpVect) * verticesList.size());
    for(unsigned int idxVect = 0; idxVect < verticesList.size(); ++idxVect)
        verts[idxVect] = verticesList[idxVect];
    //cpShape* physShape = cpPolyShapeNew(bodyToAddTo, verticesList.size(), verts, cpvzero);
    cpShape* physShape = cpPolyShapeNew(bodyToAddTo, verticesList.size(), verts, cpv(pos.x, pos.y));
	physShape->e = 0.0;
	physShape->u = 1.5;
	physShape->collision_type = 1;
	return physShape;
}

Object* getObjectByName(std::string objectName)
{
    unsigned int idxObject = 0;
    bool objectFound = getObjectIndexByName(objectName, idxObject);
    if(objectFound)
        return &objectList[idxObject];
    else
        return 0;
}

bool getObjectIndexByName(std::string objectName, unsigned int& idxObjectFound)
{
    for(unsigned int idxObject = 0; idxObject < objectList.size(); ++idxObject)
    {
        if(objectList[idxObject].name == objectName)
        {
            idxObjectFound = idxObject;
            return true;
        }
    }
    return false;
}

void deleteObjectByName(std::string objectName)
{
    unsigned int idxObject = 0;
    if(getObjectIndexByName(objectName, idxObject))
    {
        Object* obj = &objectList[idxObject];
        //if(obj->physBody != 0)
        if(obj->physShape != 0)
        {
            cpSpaceRemoveShape(space, obj->physShape);
            //cpSpaceRemoveBody(space, obj->physBody);

            cpShapeFree(obj->physShape);
            //cpBodyFree(obj->physBody);

            obj->physShape = 0;
            //obj->physBody = 0;

            std::cout << "removed\n";
        }
        //objectList.erase(objectList.begin() + idxObject);
        //delete obj;
    }
    else
        std::cout << "object "<< objectName <<" not found, not removed\n";
}

void physicsTerminate(void)
{
	cpSpaceFreeChildren(space);
	cpSpaceFree(space);
	cpBodyFree(staticBody);
}
Thanks for looking into it :)
TurboLento
Posts: 11
Joined: Mon Feb 22, 2010 11:21 pm
Contact:

Re: Changing body Velocity results in Segmentation Fault

Post by TurboLento »

I think i've figured it out. It doesn't have to do with Chipmunk, it was my code (as I feared but hoped otherwise :)). It's a recurring error for me: create a class instance inside a function, add it to a vector, and forget that it eventually gets erased due to dropping out of that function's scope and thus, Segmentation Fault occurs when accessing it.
Changing the "objectList" declaration from

Code: Select all

std::vector<Object>
to

Code: Select all

std::vector<Object*>
and creating Objects through

Code: Select all

Object* newObject = new Object;
and from there one just handling Objects as pointers seems to have fixed it.
Sorry about the confusion and thanks for all the help.
User avatar
Tam Toucan
Posts: 141
Joined: Tue Jun 23, 2009 4:26 pm
Contact:

Re: Changing body Velocity results in Segmentation Fault

Post by Tam Toucan »

Actually what you are doing is valid, but not best practice. When you create a local object on the stack then yes it disappears when it goes out of scope, but putting it on the vector will take a copy of the object i.e. create a new copy of the object. That's why it's not best practice. You are creating/copying/destroying entire objects. Using the pointer means you create one new object and then copy the pointer into the vector and the original pointer goes out of scope (so it's actually the same thing, but dealing with pointers not entire objects).

However you now need to remember to delete the objects from the vector else you'll get a memory leak (when you have actual objects in the vector their destructor's will be called when the vector goes out of scope).

So whilst that might have fixed the problem it was not the direct cause. I can't see anything obviously wrong with the code you posted (other than the memory leak of the malloc). Is that really the entire code that was crashing? I wouldn't be surprised if this comes back to bite you since I think you've hidden, not fixed, the problem :(

BTW here's a template I use to clear up vectors of new'ed objects.

Code: Select all

#ifndef UTIL_DELETE_AND_CLEAR_H
#define UTIL_DELETE_AND_CLEAR_H
#include <algorithm>

namespace Util {

//
// Functor to delete object
//
template <class DeletablePtr> class DeleteIt
{
public:
    void operator () (DeletablePtr& obj) { delete obj; }
};

//
// Helper function to delete all the objects in a container and clear it
//
template <class Container>
inline void deleteAndClear(Container& container)
{
        std::for_each(container.begin(), container.end(), DeleteIt<typename Container::value_type>());
        container.clear();
}

} // namespace

#endif
To use it you would do

Code: Select all

Util::deleteAndClear(objectList);
User avatar
Tam Toucan
Posts: 141
Joined: Tue Jun 23, 2009 4:26 pm
Contact:

Re: Changing body Velocity results in Segmentation Fault

Post by Tam Toucan »

Are you on Linux? If so get valgrind. Invaluable for tracking down stuff like this.
TurboLento
Posts: 11
Joined: Mon Feb 22, 2010 11:21 pm
Contact:

Re: Changing body Velocity results in Segmentation Fault

Post by TurboLento »

Tam Toucan wrote:Actually what you are doing is valid, but not best practice. When you create a local object on the stack then yes it disappears when it goes out of scope, but putting it on the vector will take a copy of the object i.e. create a new copy of the object. That's why it's not best practice. You are creating/copying/destroying entire objects. Using the pointer means you create one new object and then copy the pointer into the vector and the original pointer goes out of scope (so it's actually the same thing, but dealing with pointers not entire objects).
I hadn't thought of this problem, it has never happened to me. Do you have any suggestions on how to create objects in functions and add it to a vector to avoid it?
EDIT: this thread seems to point out some ways to do this, but is related to C++. I intend to program in C++ anyway, but keep away from boost as long as I can.
Tam Toucan wrote: However you now need to remember to delete the objects from the vector else you'll get a memory leak (when you have actual objects in the vector their destructor's will be called when the vector goes out of scope).
Yes, I'm aware of how the deletion of pointers in vectors should be done, just hadn't included any code to clear up memory in the end of the program yet. Thanks for pointing it out and for posting your deletion code, though.
Tam Toucan wrote: So whilst that might have fixed the problem it was not the direct cause. I can't see anything obviously wrong with the code you posted (other than the memory leak of the malloc). Is that really the entire code that was crashing? I wouldn't be surprised if this comes back to bite you since I think you've hidden, not fixed, the problem :(
I've just excluded some comments from the entire code.
Tam Toucan wrote:Are you on Linux? If so get valgrind. Invaluable for tracking down stuff like this.
Valgrind is excellent, I've used it a bit before, but now I'm on windows, so I'm only using gdb in CodeBlocks. Thanks for the tip.
Post Reply

Who is online

Users browsing this forum: Heise IT-Markt [Crawler] and 30 guests