0

I'm building a top-down view demo for a path planning/collision avoidance method. c++ in Visual Studio 2010.

When I run in Debug mode everything is fine. But when I run in Release, crazy behavior occurs. Previously my characters would speed up immensily and change direction when running into other characters, and now they are just dissapearing (probably moving somewhere outside the screen).

A search showed that this is usually because of floating point operations. I removed all floats, and Floating Point Model was already on fp:precise for both Debug and Release. I have no idea where to go from here...

I'm pretty sure this code is the source of the errors. Each character can be found in a cell. On the cell edges, the average velocity of the characters there is stored (cell->vLeft etc), and this character wants to average it's own velocity with that stored on the cell edges.

void CharacterQueryStructure_Grid::computeActualVelocity(Character& character, double dt){

// find the cell for this character
const CellCoord& cellID = _posToCell2D(character.getPosition());
int x = cellID.first, y = cellID.second;
int layerID = character.getLayer();

if(x == -1 && y == -1){ // if the position is invalid, return no neighbours
    //TODO: ERRORRRR
    //return Point(NULL, NULL);
    character.setNewVelocity_EulerIntegration(character.getPreferredVelocity(), dt);
}
else{

    //Interpolate between the four points to find the average velocity at that location
    UIC_cell* cell = uicGrids[layerID][_getCellID(x,y)];

    double distLeft = (character.getPosition().x - xMin) - cellSize * x;
    double distBot  = (character.getPosition().y - yMin) - cellSize * y;

    //First find the interpolated velocity at the location of your projection on the horizontal and vertical axes.
    Point vHor = cell->vLeft * ((cellSize - distLeft)/cellSize) + cell->vRight * (distLeft/cellSize);
    Point vVer = cell->vBot  * ((cellSize - distBot)/cellSize)  + cell->vTop * (distBot/cellSize);

    //Now interpolate these to your location
    double distHor = abs(distLeft - .5 * cellSize);
    double distVer = abs(distBot - .5 * cellSize);

    //Point vAverage = vHor * (distHor / (.5 * cellSize)) + vVer * (distVer / (.5 * cellSize));

    Point vAverage = (vHor + vVer) / 2;


    //Calculate the new velocity based on your own preferred velocity, the average velocity and the density in your cell.
    Point newVelo = character.getPreferredVelocity() + (cell->density / maxDensity) * (vAverage - character.getPreferredVelocity());

    // set it, while adhering smoothness constraints
    character.setPreferredVelocity(newVelo);
}   

}

Any help would be greatly appreciated!

Edit: And here is _posToCell2D...

CellCoord CharacterQueryStructure_Grid::_posToCell2D(const Point& pos) const
{
    int x = (int)floor((pos.x - xMin) / cellSize);
    int y = (int)floor((pos.y - yMin) / cellSize);

    // if this coordinate lies outside the grid: return nothing
    if(x < 0 || y < 0 || x >= xNrCells || y >= yNrCells)
        return CellCoord(-1,-1);

    // otherwise, return the correct cell ID
    return CellCoord(x,y);
}
Tessa
  • 297
  • 1
  • 3
  • 10
  • Sounds like undefined behaviour. – Jabberwocky Jul 22 '14 at 15:02
  • 1
    generally, I'd add lots of asserts, start the debugger and watch out for [magic numbers from MS](http://en.wikipedia.org/wiki/Magic_number_%28programming%29) – wonko realtime Jul 22 '14 at 15:06
  • 1
    Can we see the code for `_posToCell2D()`? I suspect that it's returning a local variable which goes out of scope by having `cellID` as a reference. – Steve Jul 22 '14 at 15:08
  • 1
    "When I run in Debug mode everything is fine. " I *seriously* doubt it. – John Dibling Jul 22 '14 at 15:18
  • 2
    @Tessa you might wanna have a look at [Surviving-the-Release-Version](http://www.codeproject.com/Articles/548/Surviving-the-Release-Version) and maybe [this question](http://stackoverflow.com/questions/11883074/what-does-mean-by-debug-build-and-release-build-difference-and-uses) – wonko realtime Jul 22 '14 at 15:20
  • @John, alright, everything *seems* fine ;). At least the behavior shown is as expected. – Tessa Jul 22 '14 at 15:24
  • 2
    @Tessa: You are probably evoking Undefined Behavior somewhere in your code. You might be corrputing the heap or the stack somehow. When you run in Debug mode, many of these problems are covered up by all the special stuff that's done in a Debug build, but the problem is still there. – John Dibling Jul 22 '14 at 15:25

2 Answers2

2

One common glitch when switching is the behavior of uninitialized variables. Do you ever set all of the uicGrids[][] to some initial value?

Frequently, Debug will automagically initialize these to 0 for you.. Release leaves them with whatever ram is leftover from previous usage.

Yeraze
  • 3,269
  • 4
  • 28
  • 42
  • 1
    MSVC does not initialize variables to 0 in C++. In debug, it generally initializes them to bad, but recognizable values to show errors quickly. – Steve Jul 22 '14 at 15:11
  • I do set each cell in uicGrids to a UIC_Cell. All properties of UIC_Cell are also initialized. Thanks for the tip! – Tessa Jul 22 '14 at 15:17
  • Another frequent source of differences is a side effect in asserts. – Eugene Jul 22 '14 at 15:46
  • 2
    You can turn on debug info in Release version. You can first try to also turn off compiler optimizations and reproduce the bug. If the bug disappears, turn it back on - debugging information is less reliable in this case but may still help. – Eugene Jul 22 '14 at 15:50
  • Turning off optimizations in RelWithDebInfo is a big help. Without that a lot of your variables will be garbage. – drescherjm Jul 22 '14 at 18:00
  • Found it! Thank you all for the help! By turning on Debug (@Eugene's tip), and turning off optimizations (@drescherjm's tip), I was able to find that although it was not uicGrids that was not initialized, the problem was indeed an uninitialized variable (maxDensity)! – Tessa Jul 22 '14 at 19:34
1

If none of the above guesses help then a productive method of debugging this is to temporarily add a lot of logging statements and write to a log file so you can trace the code execution and see the value of variables.

ScottMcP-MVP
  • 10,337
  • 2
  • 15
  • 15