Advertisement

Assertion failed in pathfind (c++)?

Started by July 21, 2018 02:04 AM
6 comments, last by Zakwayda 6 years, 4 months ago

Hi!

Im using a a-star pathfinder from the web ("micropather") and I've run into a problem in one of my projects using it and i'm stuck. Maybe you can give me a hint on where to look for the error?

This is the problem I get:

image.png.5984d1088d877c55b2dccb3497a23353.png

It happens every time after one agent pathfinds and another one tries to do it again. The first agent can always pathfind without problems, the second one always spawns this message.

I happens when the pather tries to push a new node to the open open list if that says anything. The failed assertion comes from:


// Add sorted. Lowest to highest cost path. Note that the sentinel has
// a value of FLT_MAX, so it should always be sorted in.
assert( pNode->totalCost < FLT_MAX );

The pathfinder works fine in other projects so I guess I made something wrong in this project but I've looked alot for possible errors...

Thank yo for any help you may provide!
Erik

Can you step through using the debugger and see what value for totalCost is causing the problem? It doesn't seem like there'd be many values of type float for which x < FLT_MAX would return false. FLT_MAX of course, maybe NaN. So it seems totalCost has become corrupted somehow or otherwise has an unexpected value.

Presumably you're providing the G and H costs, in which case you could also add checks in your own code (if you don't have them already) to make sure those are sane.

Advertisement

Yes the value of totalCost is 3.40282347e+038.

I guess that's the max value of the float?

Im not sure how it becomes this however. I found out this:

1. It happens when I try to add the first node during solving the pathfind (see below). The code continues but it crashes with that "open.Push()" function (which adds the starting node I guess).


int MicroPather::Solve( void* startNode, void* endNode, vector< void* >* path, float* cost )
{
	#ifdef DEBUG_PATH
	printf( "Path: " );
	graph->PrintStateInfo( startNode );
	printf( " --> " );
	graph->PrintStateInfo( endNode );
	printf( " min cost=%f\n", graph->LeastCostEstimate( startNode, endNode ) );
	#endif

	*cost = 0.0f;

	if ( startNode == endNode )
		return START_END_SAME;

	++frame;
//	// In "reuse" mode, reset the costs.
//	if ( pathNodeMem )
//		ReuseAll();

	OpenQueue open( graph );
	ClosedSet closed( graph );
	
	open.Push( NewPathNode( startNode,										// node
							0,												// cost from start
							graph->LeastCostEstimate( startNode, endNode ),
							0 ) );
	

2. The NewPathNode returns a node with totalCost = 3.40282347e+038 which causes the problem. See below (function continues but the "return root" at the bottom is returning the node with the strange totalCost already.


PathNode* MicroPather::NewPathNode( void* state, float costFromStart, float estToEnd, PathNode* parent )
{
	// Try to find an existing node for this state.
	unsigned key = Hash( (unsigned) state );   //(HASH_SIZE-1) & ( (unsigned)state + (((unsigned)state)>>8) + (((unsigned)state)>>16) + (((unsigned)state)>>24) );

	if ( !hashTable[key] ) {
		// There isn't even a hashtable yet - create and initialize the PathNode.
		hashTable[key] = AllocatePathNode();
		hashTable[key]->Init( frame, state, costFromStart, estToEnd, parent );
		return hashTable[key];
	}

	PathNode* root = hashTable[key];
	PathNode* up = 0;
	while ( root ) {
		up = root;
		if ( root->state == state ) {
			root->Reuse( frame, costFromStart, estToEnd, parent );
			assert( root->state == state );
			return root;
		}

Im kind of at a loss here...

I would start by checking that all costs you give to the path finder are sane. If they are not, your code is broken. If it is, the pathfinder itself is broken, ie divide and conqueror.

The value must come from somewhere. Best option is being able to point out where it is wrong, second best is eliminating as much code as possible that is not the problem. Any code that remains must then be wrong or act wrong by deduction. Repeat this divide/conqueror step until you found the cause.

One way of doing that is to add assert statements that limit the acceptable range of those values. Be sure not to build in release mode, since assert then silently disappears ?

Eliminate the first agent.  Does it still crash?  Then it's data being passed in from the second agent.  If it stops crashing that tells you something too.  Debugging is a skill honed from experience sadly.  You can read about it, but until you get first hand knowledge your learning truly does not begin :).  As @Alberth said, divide and conquer.  Make the smallest program that still reproduces the assert.

"Those who would give up essential liberty to purchase a little temporary safety deserve neither liberty nor safety." --Benjamin Franklin

It's the hashtable. Which as far as I understand is only used for optimizing (reusing already calculated nodes for other pathfinds. If I disable it it pathfands fine. But I use the exact same setup and input as in my other projects, this is what's puzzling me.

Advertisement

I've looked at the library, and it looks like you're not using the latest version. Unless you have some reason not to, the first thing I'd do is update to the latest version and see if that has any effect.

This topic is closed to new replies.

Advertisement