Page 1 of 1

random crashes in handleQueryRehashHelper

Posted: Sun Jan 31, 2010 4:53 pm
by Vexorg
I'm using the latest Chipmunk 5.0 code with Cocos2d for the iphone and I get a crash in this function randomly. It doesn't happen often but it has been happening for over a month and no matter what I do, I can never seem to fix it. I did have it crash once with the debugger up and the pointer for "elt" was bad, it was a small value like 0x343. So it is crashing from a memory access violation but how did "elt" get bad in the first place? "elt" is coming from space->activeShapes->handleSet->table->[1..x]next->elt. Any ideas what I should focus on in my code? Could it be caused by not removing shapes/bodies correctly from activeShapes? I know this might be a very broad question but my hope is someone else has run into the same issue before and remembers how they fixed it. I call cpSpaceStep 120 times a second if that info helps.

Here's the callstack and snippets of the code that match the line number:

Exception Type: EXC_BAD_ACCESS (SIGBUS)
Exception Codes: KERN_PROTECTION_FAILURE at 0x00000004

Thread 0 Crashed:
0 Program 0x00156be8 handleQueryRehashHelper (cpSpaceHash.c:431)
1 Program 0x00153fcc cpHashSetEach (cpHashSet.c:198)
2 Program 0x00156684 cpSpaceHashQueryRehash (cpSpaceHash.c:472)
3 Program 0x001556fc cpSpaceStep (cpSpace.c:659)

Code: Select all


// Hashset iterator func used with cpSpaceHashQueryRehash().
static void
handleQueryRehashHelper(void *elt, void *data)
{
	cpHandle *hand = (cpHandle *)elt;
	
	// Unpack the user callback data.
	queryRehashPair *pair = (queryRehashPair *)data;
	cpSpaceHash *hash = pair->hash;
	cpSpaceHashQueryFunc func = pair->func;

	cpFloat dim = hash->celldim;
	int n = hash->numcells;

	void *obj = hand->obj;    <******** crashes here
	cpBB bb = hash->bbfunc(obj);

---------------
void
cpHashSetEach(cpHashSet *set, cpHashSetIterFunc func, void *data)
{
	for(int i=0; i<set->size; i++){
		cpHashSetBin *bin = set->table[i];
		while(bin){
			cpHashSetBin *next = bin->next;
			func(bin->elt, data);   <******* called from here
			bin = next;
		}
	}
}
---------------
void
cpSpaceHashQueryRehash(cpSpaceHash *hash, cpSpaceHashQueryFunc func, void *data)
{
	clearHash(hash);
	
	queryRehashPair pair = {hash, func, data};  
	cpHashSetEach(hash->handleSet, &handleQueryRehashHelper, &pair); <******* called from here
}

---------------
void
cpSpaceStep(cpSpace *space, cpFloat dt)
{
	if(!dt) return; // don't step if the timestep is 0!
	
	cpFloat dt_inv = 1.0f/dt;

	cpArray *bodies = space->bodies;
	cpArray *constraints = space->constraints;
	
	// Empty the arbiter list.
	space->arbiters->num = 0;

	// Integrate positions.
	for(int i=0; i<bodies->num; i++){
		cpBody *body = (cpBody *)bodies->arr[i];
		body->position_func(body, dt);
	}
	
	// Pre-cache BBoxes and shape data.
	cpSpaceHashEach(space->activeShapes, (cpSpaceHashIterator)updateBBCache, NULL);
	
	// Collide!
	cpSpaceHashEach(space->activeShapes, (cpSpaceHashIterator)active2staticIter, space);
	cpSpaceHashQueryRehash(space->activeShapes, (cpSpaceHashQueryFunc)queryFunc, space); <********called from here

Re: random crashes in handleQueryRehashHelper

Posted: Sun Jan 31, 2010 5:48 pm
by slembcke
Are you removing objects inside of callbacks? You aren't supposed to, and that is about the only way I can think of for it to crash there.

Re: random crashes in handleQueryRehashHelper

Posted: Sun Jan 31, 2010 6:16 pm
by Vexorg
Yes I am :)

Ok, I'll try to handle this better by using cpSpaceAddPostStepCallback to remove my shapes and bodies from collision callbacks. I already have a function to collect shapes and free them at a later time though but it looks like that isn't enough.

Re: random crashes in handleQueryRehashHelper

Posted: Mon Feb 01, 2010 9:40 am
by slembcke
Yup. The post step callbacks were added after much complaining (from me too!) that you couldn't remove objects inside of callbacks. As well as a lot of crashes due to trying. It's perhaps not quite as elegant as just removing it directly, but it works pretty well and helps solve the issue of attempting to remove objects from more than one callback.

I should probably add an assertion that runs in debug mode to check that.