Cannot figure out Seg Fault, lots of detail provided

。_饼干妹妹 提交于 2019-12-13 03:55:56

问题


I asked this question about a half hour ago, but the code had typos and I wasn't being very clear, so I've deleted and I'm trying again with a better format.

I'm getting a Segmentation Fault in my code, the problem seems to be at the function call if( (*trans).test((*this), *(*itr)) ) inside World::update():

void World::update(sf::Time dt)
{
    mPlayer->setVelocity(0.f, 0.f);

    while (!mCommandQueue.isEmpty()){
                Command cmd = mCommandQueue.pop();
                cmd.action(cmd.node, dt);
    }
    mSceneGraph.update(dt);
    adaptPlayerPosition();

    //Enemy Spawn engine
    if (mSpawnTimer.getElapsedTime().asSeconds() >= SPAWN_INTERVAL && mEnemies.size() < MAX_NUM_ENEMIES){
        float winX = mWindow.getDefaultView().getSize().x;
        float winY = mWindow.getDefaultView().getSize().y;
        float x = rand() % (int)winX;
        float y = rand() % (int)winY;
        spawnEnemy(x, y, EnemyType::Loner, IState::ILWander);
        mSpawnTimer.restart();
    }

    // FSM update
    IState::ID curEnemyStateID;
    FState curEnemyState;
    bool trigger = false;
    ICondition triggeredtrans;
    FState triggeredState;
    for(auto itr = mEnemies.begin(); itr != mEnemies.end(); ++itr){
        curEnemyStateID = (*itr)->getState();

        // set curState to whatever the enemy's curState is
        switch(curEnemyStateID){
        case 0:
            curEnemyState = LWander;
            break;
        default:
            break;
        }

        auto tState = curEnemyState.getTransitionStates().begin();
        for(auto trans = curEnemyState.getConditions().begin(); trans != curEnemyState.getConditions().end(); ++trans){
            if( (*trans).test((*this), *(*itr)) ){
                trigger = true;
                triggeredState = (*tState);
                break;
            }
            ++tState;
        }
        if(trigger){
            (*itr)->setState(IState::ILRushPlayer);
            curEnemyState = LRushPlayer;
        }
        curEnemyState.getAction()->doAction((*this), *(*itr));
    }
}

Context:

trans is an iterator for a std::vector<ICondition> conditions where each ICondition has a test(World& world, Enemy& enemy). itr is an iterator through a std::vector<Enemy*> that is held by World.

The conditions vector is filled in this function:

void World::initializeStates()
{
    Wander LWanderAction;
    LWander.setAction(LWanderAction);

    DistFromPlayer LWanderCond1(30);

    LWander.pushCondition(LWanderCond1);
    LWander.pushTransitionState(LRushPlayer);
}

LWander is a state (FState) in my Finite State Machine. Wander is a class that inherits IAction, and setAction accepts an IAction parameter: FState::setAction(IAction iact)

DistFromPlayer is a class that inherits ICondition.

FState::pushCondition(ICondition icond) and FState::pushTransitionState(Fstate state) should take their arguments and push them to Fstate's conditions and states vectors. (A transition's condition and matching target state should be at the same indices in both)

LWander and LRushPlayer are both members of World.


And that should cover everything. I don't know why I'm getting a SegFault, but I'm assuming that the problem is with how things are pushed into LWander in World::initializeStates(). I should also note that the SegFault occurs right after the first enemy is spawned in my game, which is also the same update frame that runs (*trans).test(*this, **itr) for the first time. All Enemys start in the LWander state.


ICondition's virtual bool test(World& world, Enemy& enemy); is defined as:

bool ICondition::test(World& world, Enemy& enemy){
    return false;
    //returns false by default, overwritten later
}

and DistFromPlayer's bool test(World& world, Enemy& enemy); is defined as:

bool DistFromPlayer::test(World& world, Enemy& enemy)
{
    std::cout << "DistFromPlayer (LWander's Transition) was reached\n";
    return false;
}

and only contains a print statement for debugging purposes.


GDB's backtrace

#0  World::update (this=0x6464408, dt=...) at C:\...\World.cpp:97
#1  0x0040416b in GameState::update (this=0x64643f0, dt=...) at C:\...\GameState.cpp:22
#2  0x00402435 in StateStack::update (this=0x28fde0, dt=...) at C:\...\StateStack.cpp:19
#3  0x00403782 in Game::update (this=0x28fbc0, elapsedTime=...) at C:\...\Game.cpp:58
#4  0x004036a2 in Game::run (this=0x28fbc0) at C:\...\Game.cpp:48
#5  0x0040888b in main () at C:\...\main.cpp:7

回答1:


I am suspecting tState iterator. You only initialize it with begin() and increment it. I can't find any test against end() of the appropriate container. Or is it safe because of some relation between curEnemyState.getTransitionStates() and curEnemyState.getConditions() which I don't realize?



来源:https://stackoverflow.com/questions/20394749/cannot-figure-out-seg-fault-lots-of-detail-provided

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!