使用删除时随机崩溃

Random' crashes when using delete

本文关键字:随机 崩溃 删除      更新时间:2023-10-16

我正试图用C++和Allegro 4.2.3编写我的第一个简单游戏,但当我更改游戏状态时,有时会出现崩溃。当一个状态启动时,它会使用"new"运算符创建它,然后在切换到下一个状态之前使用"delete"。不过,我不确定我是否完全理解使用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打开线程.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 */
}

如果有任何帮助,我将不胜感激,因为我根本不确定问题出在哪里。

感谢您的帮助和建议,它们很有趣,很有用!然而,我认为我的问题的解决方案是使用Allegro库的新版本——我被告知使用4.2.3,但据我所知,转到4.4.2已经消除了这个问题!

Well new是从堆中分配内存,delete是释放内存。同一内存不能删除(释放)两次。您可以浏览一些关于新建/删除的教程。

虽然我还没有看过你的代码,但这里有一些你可以做的事情,1) 在gdb中运行您的代码(为了获得崩溃的堆栈跟踪,它会告诉您大部分事情)。2) 如果是因为new/delete,那么可能是因为double free,new/delete可能失败还有其他原因。3) 您可以记录调用new/delete的次数,也可以覆盖new/delete并编写自己的new/delete例程。4) 如果您不能执行以上任何操作,那么只需编写printf语句即可了解它在哪里失败。printf可能并不总是可靠的,您可以使用fflush()。

这只是程序代码的一小部分,很难判断它可能出了什么问题。

之所以会发生这种情况,是因为C++有"未定义行为"的概念,当你做错了什么(比如删除同一个对象两次)时,你不能依赖于会立即引发错误的事实,但相反,发生的是,其他事情,甚至是不相关的,可能会在以后出现奇怪的行为(甚至是后来执行的数百万条指令)。

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

完全有可能你在代码的其他部分犯了错误,你在delete调用中看到了错误,但这只是所发生事情的"受害者",而不是问题所在。

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

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