mspraggs / potentia

Southampton Game Jam 2015
0 stars 0 forks source link

std::out_of_range thrown on win #1

Closed mspraggs closed 9 years ago

mspraggs commented 9 years ago

After playing the ten levels required to win, then clicking the retry balloon, an exception is thrown because a vector is being indexed out of its bounds. Console output:

You won! Loaded 1 guns Info: Loading room file david levels/Lv6.txt terminate called after throwing an instance of 'std::out_of_range' what(): vector::_M_range_check [1] 3631 abort (core dumped) ./game

DivFord commented 9 years ago

I think there might be a memory leak as well though. I fell asleep with it running, and woke up to a segfault… I'll try to run it while I'm awake and get some better debug info.

DivFord commented 9 years ago

Here is the bug report from the out of range exception:

Thread 0 Crashed:: Dispatch queue: com.apple.main-thread 0 libsystem_kernel.dylib 0x00007fff8b620ce2 pthread_kill + 10 1 libsystem_c.dylib 0x00007fff9016f7d2 pthread_kill + 95 2 libsystem_c.dylib 0x00007fff90160a7a abort + 143 3 libc++abi.dylib 0x00007fff8db0b7bc abort_message + 214 4 libc++abi.dylib 0x00007fff8db08fcf default_terminate() + 28 5 libobjc.A.dylib 0x00007fff92ada1cd _objc_terminate + 114 6 libc++abi.dylib 0x00007fff8db09001 safe_handler_caller(void (*)()) + 11 7 libc++abi.dylib 0x00007fff8db0905c std::terminate() + 16 8 libc++abi.dylib 0x00007fff8db0a152 cxa_throw + 114 9 libc++.1.dylib 0x00007fff8f4acd6b std::1::vector_base_common::__throw_out_of_range() const + 71 10 libbackend.dylib 0x000000010154bb6d std::1::vector<Prop, std::1::allocator >::at(unsigned long) + 77 (vector:1402) 11 libbackend.dylib 0x00000001015492c3 Game::outro() + 2067 (Game.cpp:126) 12 libbackend.dylib 0x0000000101547efe Game::run() + 334 (Game.cpp:46) 13 game 0x000000010150ba81 main + 65 (main.cpp:11) 14 game 0x000000010150ba34 start + 52

mspraggs commented 9 years ago

Ah I get this now. I ran the game under gdb (the gnu debugger) and inspected the CURRENT_ROOM when the exception is thrown. The line it's failing on is this:

return CURRENT_ROOM.getProps()->at(0).code() == 'y';

getProps returns a pointer to the props vector, and this has size zero, hence calling at(0) on the vector raises an exception. This is slightly odd as there's a beforehand while loop that should ensure that should ensure that the props are there.

DivFord commented 9 years ago
while(!INPUT.quit() && !(CURRENT_ROOM.getProps()->size() < 2 && WINDOW.faded())) {
        INPUT.scan();

        World::instance().update();
        you_.update();

        if(CURRENT_ROOM.getProps()->size() < 2)
            WINDOW.fadeOut();

        World::instance().draw();
        you_.draw();

        WINDOW.print("Quit", Vector(0.2f, 0.6f), WHITE);
        WINDOW.print("Retry", Vector(0.7f, 0.6f), WHITE);

        WINDOW.flush();
    }

    return CURRENT_ROOM.getProps()->at(0).code() == 'y';

I may be wrong, but doesn't the condition on the while-loop at the top mean that if WINDOW.faded() returns false, the function returns even if props is zero-length? (This is game::outdo, btw)

Edit: Nope, that's nonsense. I read the && as an || for some reason...

DivFord commented 9 years ago

Woo! I fixed it.

A couple of problems:

to leave the loop in Game::run(), which was checking for fadeout on death, but not on winning. Since we have a few different things checking _hasFaded(), that caused an infinite room load loop if outro returned true.