【问题标题】:Random' crashes when using delete使用删除时随机崩溃
【发布时间】:2015-02-26 06:08:32
【问题描述】:

我正在尝试使用 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会打开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 */
}

我将非常感谢任何帮助,因为我完全不确定问题出在哪里。

【问题讨论】:

  • 查看调用堆栈,直到你找到你的代码。这就是崩溃的来源。我在您发布的代码中没有看到任何有关线程的信息,因此很难说问题可能是什么。您可能会删除两次,您可以在删除它们后将指针设置为 nullptr 以防止出现这种情况,但最好先弄清楚原因。状态逻辑很尴尬。

标签: c++ pointers allegro


【解决方案1】:

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

【讨论】:

    【解决方案2】:

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

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

    【讨论】:

      【解决方案3】:

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

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

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

      很可能您在代码的其他部分犯了错误,并且您在 delete 调用中看到了错误,但这只是所发生事情的“受害者”,而不是问题所在。

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

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

      【讨论】:

        猜你喜欢
        • 2019-04-04
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 2014-10-17
        • 2013-08-23
        • 2013-04-21
        • 2011-08-13
        相关资源
        最近更新 更多