0

I'm trying to write my first simple game using C++ and Allegro 4.2.3, but I'm getting crashes that sometimes occur when I change the game-state. When a state is started it uses the 'new' operator to make it, and then uses 'delete' before switching to the next one. I'm not sure if I fully understand using the new and delete operators, though! Here's a selection of code:

enum    //Game state
{
    TITLE_SCREEN, CUTSCENE_1
};

int main(void)
{
    const int screenwidth = 800;
    const int screenheight = 600;
    bool quit = false;
    int state = TITLE_SCREEN;
    int oldstate = -1;
    int oldoldstate;
    init(screenwidth, screenheight);
    install_int(counter, (1000/FPS));
    TitleState *Title;
    Cutscene *Scene1;

    srand (time(NULL));

    while (!quit) 
    {
        while(tick == 0)
        {
            rest(1);
        }
        while(tick > 0)
        {
            oldoldstate = oldstate;
            oldstate = state;
            switch(state)
            {
            case TITLE_SCREEN:
                //If the last state is different to this one, create the state
                if(oldoldstate != TITLE_SCREEN)
                {
                    Title = new TitleState();
                }
                //Run the program in the state
                Title->Play();
                //Check the state to see if it has changed
                state = Title->CheckState();
                //If the state has changed, delete the current state
                if(oldstate != state)
                {
                    delete Title;
                }
                break;
            case CUTSCENE_1:
                if(oldoldstate != CUTSCENE_1)
                {
                    Scene1 = new Cutscene();  //SOMETIMES CRASHES BEFORE HERE
                }
                Scene1->Play();
                state = Scene1->CheckState();
                if(oldstate != state)
                {
                    delete Scene1;
                }
                break;
            case EXIT:
                quit = true;
                break;
            default:
                allegro_message("Game state not found!");
                exit(-1);
            }
            int oldtick = tick;
            tick--;
            if(oldtick <= tick)
                break;
        }

    }
    deinit();
    return 0;
}

When the program crashes, VS2010 opens up thread.c to show where the error was:

static void _callthreadstart(void)
{
    _ptiddata ptd;           /* pointer to thread's _tiddata struct */

    /* must always exist at this point */
    ptd = _getptd();
    /*
     * Guard call to user code with a _try - _except statement to
     * implement runtime errors and signal support
     */
    __try
    {
        ( (void(__CLRCALL_OR_CDECL *)(void *))(((_ptiddata)ptd)->_initaddr) )
            ( ((_ptiddata)ptd)->_initarg );    //ERROR HERE (Next statement to be executed)

        _endthread();
    }
__except ( _XcptFilter(GetExceptionCode(), GetExceptionInformation()) )
    {
            /*
                * Should never reach here
                */
            _exit( GetExceptionCode() );

    } /* end of _try - _except */
}

I would greatly appreciate any help, because I'm not sure at all what the problem is.

Brian Tompsett - 汤莱恩
  • 5,753
  • 72
  • 57
  • 129
Nin
  • 11
  • 2
  • Look back up the callstack until you hit your code. That's where the crash is coming from. I don't see anything about threads in the code you posted, so it's hard to say what the problem might be. You may be deleting something twice, you could set the pointers to nullptr after you delete them to guard against that, but better to figure out why first. The state logic is pretty awkward. – Retired Ninja Feb 26 '15 at 06:18

3 Answers3

1

Thanks for the help and suggestions, they are interesting and useful to know! However, I think the solution to my problem was to use a newer version of the Allegro library - I was told to use 4.2.3 for this but moving to 4.4.2 has removed this problem as far as I can tell!

Nin
  • 11
  • 2
0

Well new is to allocate memory from the heap, and delete is to release it. You can not delete (release) the same memory twice. You can go through some tutorial about new/delete.

Though I have not gone through your code, but here are few things you can do, 1) run your code in gdb (to get a stacktrace of your crash, it will tell most of the things to you). 2) If it is because of new/delete, then may be it is because of double free, there are other reasons why new/delete may fail. 3) You can keep a count of number of times new/delete gets called, you can override new/delete and write your own new/delete routine. 4) If you can not do anything of the above, then simply write printf statements to get to know where it is failing. printf may not be always reliable, you can use fflush().

D Untouchable
  • 332
  • 4
  • 9
0

This is a tiny fraction of the code of the program and it's hard to tell what it could be wrong.

This happens because C++ has the concept of "undefined behavior" and when you do something wrong (like for example deleting the same object twice) you cannot rely on the fact that an error will be raised immediately, but what happens is instead that something else, even unrelated, may behave strangely later (even millions of instructions executed later).

One of the basic assumptions of the language is that programmer don't do this kind of error (go figure!).

It's perfectly possible that you made a mistake in other parts of the code and you see the error in that delete call, that is however just the "victim" of what happened, not the point where the problem is.

There are some general rules that can help preventing allocation/deallocation errors (like using standard containers instead of naked pointers and follow the rule of the "big three").

Every time you write an instruction in a C++ program you should think a lot, because if you let a logical bug in it will be very very hard to remove it later. This is less of an issue in languages where "undefined behavior" is not present at language level.

6502
  • 112,025
  • 15
  • 165
  • 265