2013-05-28 3 views
3

У меня есть приложение DirectX. Это очень просто, но у меня проблема с этим. Я создаю устройство, контекст устройства и т. Д., И все работает, но когда я ухожу, происходит сбой и возникает ошибка: HEAP: Free Heap block 3ad7d18 modified at 3ad7d98 after it was freed. Это происходит, только если я вызываю функцию IDXGISwapChain Present хотя бы один раз. Если я этого не сделаю, весь процесс очистки пройдет хорошо. Более того, я вызываю Release на каждый объект COM, и авария ALWAYS возникает только тогда, когда я выпускаю последний COM-объект (заказ не имеет значения). Я использую DirectX 11 (Win8 SDK) на Windows 7, MS Visual 2012Сбой при очистке Приложение DirectX

Моя функция цикл сообщений:

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

Основная функция, в которой я инициализировать и начать свой Engi пе:

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. 

Shutdown:

// 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; } } 
+0

Один быстрый комментарий к вашему коду процедуры окна: WM_QUIT никогда не будет обращаться к процедуре окна, поскольку он предназначен как сигнал к насосу сообщений (ваш вызов PeekMessage), что все окна программы были и что программа также должна закрыться. Ваша проверка WM_QUIT должна идти после вызова PeekMessage, но перед вызовом Translate/DispatchMessage. Вам может понадобиться WM_CLOSE, который запускается всякий раз, когда пользователь запрашивает закрыть окно (т. Е. Нажимает кнопку X или нажимает ALT + F4 или выбирает Close из меню Window). Также ваш стиль кода напоминает мне о Фрэнке Луне ... – Alex

+0

Я думаю, что вы правы с сообщением WM_QUIT, спасибо :) Теперь это довольно старый код. Я начал использовать интеллектуальные указатели и умные указатели. И у меня есть книга Фрэнка Луны. Это для DirectX 11 и мне это нравится :) –

ответ

3

Хорошо ... Это действительно раздражает. Этот код, кажется, хорош, и проблема была в драйверах или sth. Когда я установил новые драйверы и перезагрузил компьютер дважды, проблема исчезла.

+0

Какой драйвер вы использовали? – Abhinav

+0

Я не уверен. Прежде всего, у меня есть GeForce 540M. Теперь я использую драйвер v. 320.18 с ПО NVIDIA GeForce Experience, которого у меня не было до обновления ... Я могу оценить только время, прошедшее с момента последнего обновления драйверов. Может быть, было 3 месяца, но я не уверен, извините :( –

0

Для чего это важно, я точно так же исправил эту проблему. Происходил только с 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 реализации. Они являются членами класса и самоуничтожаются в обратном порядке строительства. Таким образом, нет ->Release() стоков :)

Смежные вопросы