简体   繁体   中英

C++ crash on Android but not on iOS

I'm developing a game on iOS and Android in C++ using cocos2d-x. I have a function that implements the A* pathfinding algorithm. I have developed and tested this on iOS and it works flawlessly. On Android, however, this function causes a crash. How is it possible that the same C++ logic will run smoothly on the one device, but not on the other?

Unfortunately the function is a rather large one, but I'll post it anyway. If it's too long to read through, I'll be happy with some general pointers regarding the sort of pitfalls that may cause a crash on one device device but not the other. Here's what I think is happening. A pathStep struct (which contains a few ints, and also has a pathStep pointer to its 'parent' (the previous step) for the initial step is created. Its index is set to equal the start index, and its address is added to the open list. Somehow, though, when it's retrieved from the open list at the beginning of the loop, its index has changed from whatever it was set to to 0.

Here's the function:

std::vector<pathStep*> GameLayer::findPathBetweenPoints(int startIndex, int targetIndex){

std::list<pathStep*> openList;
std::list<pathStep*> closedList;

pathStep startStep;
startStep.index = startIndex;
startStep.fromStartDist = 0;
startStep.toEndDist = boardDistanceBetweenPoints(startIndex, targetIndex);
startStep.parent = nullptr;

openList.push_back(&startStep);

//PATH FINDING LOOP

do {

//get lowest scoring from open list

int lowestScore = 10000;
pathStep* currentStep;
int currentStepOpenListIndex;
int olIndex = 0;

for (std::list<pathStep*>::iterator i = openList.begin(); i!= openList.end(); i++) {
    pathStep *step = *i;
    if (step->score < lowestScore) {
        currentStep = step;
        lowestScore = step->score;
        currentStepOpenListIndex = olIndex;
    }
    olIndex++;
}
Hexagon *currentHexagon = _hexagons.at(currentStep->index);

//check if it is the target
if (currentStep->index == targetIndex) {
    cocos2d::log("target found!!!!!");
    //return route between points
    std::vector<pathStep*> finalRoute;
    pathStep *step = currentStep;
    for (; ; ) {
        cocos2d::log("step index = %d", step->index);

        finalRoute.push_back(step);
        if (step->index == startIndex) {
            return finalRoute;
        }
        step = step->parent;
    }
}

//remove the current step from the open list and add it to the closed list
    std::list<pathStep*>::iterator iterator = openList.begin();
    std::advance(iterator, currentStepOpenListIndex);
    openList.erase(iterator);

closedList.push_back(currentStep);

//get the adjacent nodes
std::vector<pathStep*> walkableSteps = currentHexagon->getWalkableSteps();
cocos2d::log("num walkable steps returned by hexagon at index %d is %lu", currentHexagon->getIndex(), walkableSteps.size());

//set the parent to the current node
for (int i = 0; i < walkableSteps.size(); i++) {
    pathStep *step = walkableSteps.at(i);
    step->parent = currentStep;

}

//score the walkable steps and add to open list if not already in either list
for (int i = 0; i < walkableSteps.size(); i++) {

    pathStep *step = walkableSteps.at(i);
    step->fromStartDist = currentStep->fromStartDist +1;
    step->toEndDist = boardDistanceBetweenPoints(step->index, targetIndex);
    step->score = step->fromStartDist + step->toEndDist;

    bool isInOpenList = false;
    bool isInClosedList = false;

    //check if is in open list
    for (std::list<pathStep*>::iterator i = openList.begin(); i!= openList.end(); i++) {
        pathStep *olStep = *i;
        if (olStep->index == step->index) {
            isInOpenList = true;
        }
    }
    //check if is closed list
    for (std::list<pathStep*>::iterator i = closedList.begin(); i!= closedList.end(); i++) {
        pathStep *clStep = *i;
        if (clStep->index == step->index) {
            isInClosedList = true;
        }
    }

    //if is not in either list, add to the open list
    if (isInClosedList == false && isInOpenList == false) {
        openList.push_back(step);
    }

}

} while (openList.size() != 0);

cocos2d::log("couldn't find valid path");
std::vector<pathStep*> path;
return path;
}

Here are the console logs from a successful run on iOS:

hexagon index 12 //this is the start position
hexagon index 36 //this is the end position
num walkable steps returned by hexagon at index 12 is 4 //from the start position, finds the shortest route to the end position
num walkable steps returned by hexagon at index 21 is 5
num walkable steps returned by hexagon at index 11 is 4
num walkable steps returned by hexagon at index 29 is 6
num walkable steps returned by hexagon at index 20 is 5
num walkable steps returned by hexagon at index 10 is 5
num walkable steps returned by hexagon at index 38 is 6
num walkable steps returned by hexagon at index 28 is 5
num walkable steps returned by hexagon at index 37 is 5
num walkable steps returned by hexagon at index 27 is 4
target found!!!!!
step index = 36 //printing the route back to the start position
step index = 37
step index = 38
step index = 29
step index = 21
step index = 12
go taken //success!

Here's the console logs from an unsuccessful run on Android:

hexagon index 25 //this is the start position
hexagon index 38 //this is the end position
num walkable steps returned by hexagon at index 0 is 1 //Android always starts at index 0, this looks like it is where the problem arises
num walkable steps returned by hexagon at index 9 is 4
num walkable steps returned by hexagon at index 19 is 6
num walkable steps returned by hexagon at index 18 is 3
num walkable steps returned by hexagon at index 10 is 5
num walkable steps returned by hexagon at index 28 is 5
target found!!!!!
step index = 38
step index = 28
step index = 19
step index = 9
step index = 0
step index = -2125467415 //follows the pointers back until it finds start index, as the initial index was incorrect, keeps going until it ends up in undefined memory
Fatal signal 11 (SIGSEGV) at 0x0a58e044 (code=1), thread 862 (ren.numberboard)

Lastly, here's the crash log from Android (which doesn't seem to tell me much):

********** Crash dump: **********
Build fingerprint: 'generic/sdk/generic:4.3/JWR66V/737497:eng/test-keys'
pid: 778, tid: 793, name: UNKNOWN  >>> com.stevebarnegren.numberboard <<<
signal 11 (SIGSEGV), code 1 (SEGV_MAPERR), fault addr 0a58e044
Assertion failed: (debug_str_.is_mapped() && index < debug_str_.size()), function get_debug_str, file elff/elf_file.h, line 300.
Stack frame #00  pc 001633d4  /data/app-lib/com.stevebarnegren.numberboard-1/libcocos2dcpp.so (GameLayer::findPathBetweenPoints(int, int)+147)Abort trap: 6

Thanks for any help!

A probable cause is this line

openList.push_back(&startStep);

It's hard to follow your code (way to much of it!) but if this pointer is ever pushed to the vector being returned, and you dereference this pointer, then you have undefined behavior . You can't return, in any way, pointers or references to local variables. Once leaving the scope a local variable was defined in, that local variable is "destructed".

As for why is seems to work on one platform and not on another, it's because undefined behavior is, well, undefined. Anything could happen.

Maybe because it reached step index of step index = -2125467415 , and finalRoute.push_back(step); is not well implemented so when it goes to the address of object with index of -2125467415 it can't access it and crash

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM