使用删除时随机'崩溃

时间:2015-02-26 06:08:33

标签: c++ pointers allegro

我试图用C ++和Allegro 4.2.3编写我的第一个简单游戏,但是当我改变游戏状态时,我有时会发生崩溃。当状态开始时,它使用“新”状态。运营商制作它,然后使用'删除'在切换到下一个之前。不过,我不确定我是否完全理解使用new和delete运算符!这是一个代码选择:

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;
}

当程序崩溃时,VS2010会打开thread.c来显示错误的位置:

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 */
}

我非常感谢任何帮助,因为我根本不确定问题是什么。

3 个答案:

答案 0 :(得分:1)

感谢您的帮助和建议,他们很有趣,也很有用!但是,我认为我的问题的解决方案是使用更新版本的Allegro库 - 我被告知使用4.2.3,但据我所知,移至4.4.2已经消除了这个问题!

答案 1 :(得分:0)

新的是从堆中分配内存,而删除是为了释放它。 您不能删除(释放)两次相同的内存。您可以阅读一些关于new / delete的教程。

虽然我没有查看你的代码,但是你可以做的事情很少, 1)在gdb中运行你的代码(为了获得崩溃的堆栈跟踪,它会告诉大部分事情)。 2)如果是因为new / delete,那么可能是因为double free,还有其他原因导致new / delete失败。 3)您可以保持调用new / delete的次数,您可以覆盖new / delete并编写自己的新/删除例程。 4)如果您无法执行上述任何操作,则只需编写printf语句即可了解失败的位置。 printf可能并不总是可靠的,你可以使用fflush()。

答案 2 :(得分:0)

这只是程序代码的一小部分,很难说它可能是错误的。

这是因为C ++具有“未定义行为”的概念,当你做错了(例如删除相同的对象两次)时,你不能依赖于立即引发错误这一事实,但会发生的是其他东西,甚至是无关的,可能会在以后表现得很奇怪(甚至以后会执行数百万条指令)。

该语言的一个基本假设是程序员不会做这种错误(如图!)。

你完全有可能在代码的其他部分犯了一个错误,你看到delete调用中的错误,然而这只是所发生事件的“受害者”,而不是问题所在的点

有一些通用规则可以帮助防止分配/释放错误(比如使用标准容器而不是裸指针,并遵循“三巨头”的规则)。

每次在C ++程序中编写指令时,都应该考虑很多,因为如果你让一个逻辑错误很难在以后删除它。在语言层面不存在“未定义行为”的语言中,这不是一个问题。