【问题标题】:Crash while cleaning DirectX application清理 DirectX 应用程序时崩溃
【发布时间】:2013-05-28 18:24:53
【问题描述】:

我有一个 DirectX 应用程序。这很简单,但我有一个问题。我创建设备、设备上下文等,一切正常,但是当我退出时,发生崩溃,错误是:HEAP: Free Heap block 3ad7d18 modified at 3ad7d98 after it was freed。仅当我至少调用一次 IDXGISwapChain Present 函数时才会发生这种情况。如果我不这样做,那么整个清洁过程就会顺利进行。此外,我在每个 COM 对象上调用 Release,并且只有在我释放最后一个 COM 对象时才会发生崩溃(顺序无关紧要)。我在 Windows 7、MS Visual 2012 上使用 DirectX 11 (Win8 SDK)。

我的消息循环函数:

int Engine::run( ){

    MSG msg = { 0 };
    mTimeCounter->restart( ); // doesn't matter
    while( msg.message != WM_QUIT ){ 
        if( PeekMessage( &msg, 0, 0, 0, PM_REMOVE ) ){
            TranslateMessage( &msg );
            DispatchMessage( &msg );
        } else {
            updateScene( mTimeCounter->deltaTime( ) );
            drawScene( );  
        }  
    }

    return static_cast<int>( msg.wParam );
}

updateScene 现在什么都不做,绘制场景只调用这两个函数:

void Engine::sceneBegin( ){
    static FLOAT color[] = { 0.05f, 0.15f, 0.05f, 1.0f }; 
    mDeviceContext->ClearRenderTargetView( mBackBufferView, color );
    mDeviceContext->ClearDepthStencilView( mDepthStencilView, D3D11_CLEAR_DEPTH | D3D11_CLEAR_STENCIL, 1, 0 );
}


void Engine::sceneEnd( ){
    mSwapChain->Present( 0, 0 ); // crash do not occure if i comment this line of code
}

部分消息切换:

   case WM_QUIT : // i do not receive it even once because i press window's X button and it destroy window before i could receive WM_QUIT ( or not? :P )
    {

                DestroyWindow( mMainWnd );
            }
            break;

            case WM_DESTROY : // i receive it if press window's X button
            {
                PostQuitMessage( 0 ); 
            }  
            break;
return DefWindowProc( hWnd, msg, wParam, lParam );

我初始化和启动引擎的主要函数:

EngTest *eng = new EngTest( );
eng->initialize( hInstance, L"Hi", show );
int r = eng->run( );
delete eng; // crash occures here but only if i call Present at least once.

关机:

// called in Engine's destructor
void Engine::shutdown( ){ 
    RELEASE_COM( mDepthStencilView );
    RELEASE_COM( mDepthStencilBuffer );
    RELEASE_COM( mBackBufferView );
    RELEASE_COM( mSwapChain );
    if( mDeviceContext )
        mDeviceContext->ClearState( );
    RELEASE_COM( mDeviceContext );
    RELEASE_COM( mDevice );  
}

RELEASE_COM

#define RELEASE_COM( x ) { if( x != NULL ) { x->Release( ); x = NULL; } }

【问题讨论】:

  • 对您的窗口过程代码的快速评论:WM_QUIT 永远不会进入窗口过程,因为它意味着程序的窗口已全部关闭的消息泵(您的 PeekMessage 调用)的信号下来,该程序也应该关闭。您对 WM_QUIT 的检查应该在调用 PeekMessage 之后,但在调用 Translate/DispatchMessage 之前进行。您可能需要 WM_CLOSE,只要用户请求关闭窗口(即点击 X 按钮或按 ALT+F4 或从窗口菜单中选择关闭),就会触发它。你的代码风格也让我想起了 Frank Luna 的......
  • 我认为你对 WM_QUIT 消息是正确的,谢谢 :) 现在它是相当旧的代码。我开始使用智能指针和 com 智能指针。我有一本弗兰克·卢纳的书。这适用于 DirectX 11,我喜欢它 :)

标签: c++ directx directx-11


【解决方案1】:

好吧...这真的很烦人。这段代码似乎很好,问题出在驱动程序或某事上。当我安装新的驱动程序并重新启动电脑两次后,问题就消失了。

【讨论】:

  • 您使用的是哪个驱动程序?
  • 我不确定。首先,我有 GeForce 540M。现在我正在使用驱动程序 v. 320.18 和 NVIDIA GeForce Experience 软件,这是我在更新之前没有的......我只能估计自上次驱动程序更新以来经过的时间。也许是 3 个月,但我不确定,抱歉 :(
【解决方案2】:

值得一提的是,这就是我修复完全相同问题的方法。仅在渲染代码中出现 Clear() 并且仅在 D3D11_CREATE_DEVICE_DEBUG 处于打开状态时发生(添加到谜)

case WM_CLOSE: // X clicked or Alt+F4
    ::DestroyWindow(hWnd); // triggers WM_DESTROY
    break;
case WM_DESTROY:
    gD3d11Context->ClearState();
    PostQuitMessage(0); // this triggers the WM_QUIT to break the loop
    break;

另外,我的指针包含在自定义 ComPtr 实现中。它们是类的成员,并以相反的构造顺序自毁。所以没有-&gt;Release() 堆栈:)

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 2011-08-26
    • 2021-12-16
    • 1970-01-01
    • 2018-11-12
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多