WM_CLOSE und Release(); verursacht "unbehandelte Ausnahme"



  • Guten Abend,

    Jeden Tag ein neues Problem x) Ich hoffe ich komme irgendwann alleine klar.
    ich arbeite momentan an einem Projekt und möchte es auch schön modular gestalten.
    Es existiert eine main.cpp, in die ich eine selbstgeschriebene .dll Datei einbinde. Mit dieser .dll möchte ich hauptsächlich Directx für mein Projekt initialisieren. (Es scheint auch alles zu funktionieren.) Dafür kommt von der .dll die Klasse:

    namespace wddx
    {
      class __declspec(dllexport) wDC_directx
      {
        public:
    
          wDC_directx();
          ~wDC_directx();
    
          void wD_initD3D(HWND, IDXGISwapChain*, ID3D11Device*, ID3D11DeviceContext*, UINT, bool);
          void wD_cleanD3D(IDXGISwapChain*, ID3D11Device*, ID3D11DeviceContext*);
      };
    }
    

    Das Aufrufen der wD_initD3D(); Methode funktioniert soweit in der main.cpp auch. Das Fenster wird beim Debuggen auch ganz normal erstellt und ist so wie ich es haben will. Die wD_cleanD3D(); ist ebenfalls unten in der main Funktion vor dem return Wert vertreten und gibt beim kompilieren auch keinen Fehler aus.

    Schließe ich aber das Fenster, wodurch ja die wD_cleanD3D(); Methode zum Einsatz kommt, erscheinen in der Debug Ausgabe die Fehler:

    Eine Ausnahme (erste Chance) bei 0x5b2010d6 (wddxdll.dll) in swfc_dev.exe: 0xC0000005: Zugriffsverletzung beim Lesen an Position 0x00000000.
    Unbehandelte Ausnahme bei 0x771515de in swfc_dev.exe: 0xC0000005: Zugriffsverletzung beim Lesen an Position 0x00000000.
    

    Dieser Fehler tritt nachweislich ja erst auf, wenn ich versuche das Fenster zu schließen und der visuelle Debug Zeiger zeigt auch auf "return" in der main-Funktion.

    Die wD_cleanD3D(); Methode ist recht simpel aufgebaut:

    void wDC_directx::wD_cleanD3D
    (
      IDXGISwapChain* wD_swapchain, 
      ID3D11Device* wD_dev, 
      ID3D11DeviceContext* wD_devcon
    )
    {
      wD_swapchain->Release();
      wD_dev->Release();
      wD_devcon->Release();
    }
    

    Die main.cpp Datei enthält sonst auch keine weiteren Überraschungen. ich erstelle global vorher das Objekt meiner Klasse (aus der .dll Datei) und wende die Methoden an.

    #include <windows.h>
    #include <d3d11.h>
    #include <d3dx11.h>
    #include <d3dx10.h>
    
    #include "wD_globals.h"
    #include G_DIRWINPROC
    #include G_DIRDX
    using namespace wddx;
    
    IDXGISwapChain * wD_swapchain; // <--
    ID3D11Device * wD_dev; // <--
    ID3D11DeviceContext * wD_devcon; // <--
    wDC_directx dxobj; // <--
    
    int WINAPI WinMain(HINSTANCE hInstance, HINSTANCE hPrevInstance, LPSTR lpCmdLine, int nCmdShow)
    {
      HWND wD_hwnd;
      WNDCLASSEX wD_wc;
      MSG wD_msg;
      RECT wD_adjwinintro = {0, 0, G_WININTROX, G_WININTROY};
    
      ZeroMemory(&wD_wc, sizeof(WNDCLASSEX));
    
      wD_wc.cbSize			= sizeof(WNDCLASSEX);
      wD_wc.style			= CS_HREDRAW | CS_VREDRAW;
      wD_wc.lpfnWndProc		= wD_WindowProc;
      wD_wc.hInstance		= hInstance;
      wD_wc.hCursor			= LoadCursor(NULL, IDC_ARROW);
      wD_wc.hbrBackground	        = (HBRUSH)COLOR_WINDOW;
      wD_wc.lpszClassName	        = G_WNDCLASS1;
    
      RegisterClassEx(&wD_wc);
      AdjustWindowRect(&wD_adjwinintro, WS_OVERLAPPEDWINDOW, FALSE);  
    
      wD_hwnd = CreateWindowEx
      (
        NULL, 
        G_WNDCLASS1,
        G_TITLE,
        WS_OVERLAPPEDWINDOW,
        G_CENTERX(G_WININTROX),
        G_CENTERY(G_WININTROY),    
        wD_adjwinintro.right - wD_adjwinintro.left,    
        wD_adjwinintro.bottom - wD_adjwinintro.top,    
        NULL,
        NULL,
        hInstance,
        NULL
      );
    
      ShowWindow(wD_hwnd, nCmdShow);
    
      dxobj.wD_initD3D
      (
        wD_hwnd, 
        wD_swapchain, 
        wD_dev, 
        wD_devcon, 
        1, 
        1
      ); // <--
    
      while(1)
      {
        if(PeekMessage(&wD_msg, NULL, 0, 0, PM_REMOVE))
        {
          TranslateMessage(&wD_msg);
          DispatchMessage(&wD_msg);
    
          if(wD_msg.message == WM_QUIT) break;
        }
        else
        {
    
        }
    }
    
      dxobj.wD_cleanD3D(wD_swapchain, wD_dev, wD_devcon);
      return wD_msg.wParam;
    }
    

    Momentan habe ich keine Lösung, versuche es aber weiter. Über Hilfe wäre ich dennoch dankbar.



  • Morgen,

    ich habe mal den Rückgabewert von wD_initD3D(); abgefragt. Diese Methode gibt S_OK zurück. Theoretisch müsste die Initialisierung von D3D ja geklappt haben.

    resultDEBUG = dxobj.wD_initD3D
    (
      wD_hwnd, 
      wD_swapchain, 
      wD_dev, 
      wD_devcon, 
      1, 
      1
    ); // <--
    
    if(resultDEBUG == S_OK) MessageBox(wD_hwnd, L"S_OK", L"OK", MB_OK);
    


  • Padmad schrieb:

    Eine Ausnahme (erste Chance) bei 0x5b2010d6 (wddxdll.dll) in swfc_dev.exe: 0xC0000005: Zugriffsverletzung beim Lesen an Position 0x00000000.
    Unbehandelte Ausnahme bei 0x771515de in swfc_dev.exe: 0xC0000005: Zugriffsverletzung beim Lesen an Position 0x00000000.
    
    void wDC_directx::wD_cleanD3D
    (
      IDXGISwapChain* wD_swapchain, 
      ID3D11Device* wD_dev, 
      ID3D11DeviceContext* wD_devcon
    )
    {
      assert( (wD_swapchain?0:puts("wD_swapchain ist 0"),wD_swapchain) );wD_swapchain->Release(); 
      assert( (wD_dev?0:puts("wD_dev ist 0"),wD_dev) );wD_dev->Release(); 
      assert( (wD_devcon?0:puts("wD_devcon ist 0"),wD_devcon) );wD_devcon->Release(); 
    }
    

    Klassischer Fall der Dereferenzierung eines NULL-Zeigers.
    Mind. einer der 3 Parameter ist zu dem Zeitpunkt NULL.

    Padmad schrieb:

    Die wD_cleanD3D(); ist ebenfalls unten in der main Funktion vor dem return Wert vertreten und gibt beim kompilieren auch keinen Fehler aus.

    Was der Compiler zur Compilezeit machen kann, macht er, z.B. auf Fehler/Unsinn hinweisen, zur Laufzeit hast du keine automatische Prüfinstanz mehr, die deinen Code prüft, da musst du schon selbst ran.

    {
    ...
      dxobj.wD_cleanD3D(wD_swapchain, wD_dev, wD_devcon);
      return wD_msg.wParam;
    }
    

    Müll. Schrottiges Design.
    Warum benutzt du eine Klasse, wenn du deren Schnittstellen nicht nutzt?
    Genau für deinen Fall hier gibt es Destruktoren. Schon mal gehört?
    Lass den ganzen Klassenmüll sein und programmiere mit struct+Funktionen, das kommt deinen Programmiergewohnheiten besser entgegen.



  • Danke erstmal für die Antwort. Den Destruktor habe ich ja extra definiert, damit ich ihn direkt oder indirekt verwenden kann. Das hab ich zuerst versucht, anstelle der Methode "wD_cleanD3D();". Das brachte aber den selben Fehler. Aus irgendeinem Grund funktioniert aber der Aufruf des Destruktor jetzt, ich vermute, weil ich als ich den Destruktor eingesetzt habe noch nicht ganz fit mit meiner .dll Datei war.

    Die Frage ist ja jetzt, da der Destruktor ja jetzt funktioniert, ob ich wD_cleanD3D(); überhaupt brauche?

    Ob einer der Parameter NULL ist, teste ich gleich mal, wobei ich nicht verstehen würde wieso, da die Funktion D3D11CreateDeviceAndSwapChain ja die Zeiger verarbeitet und die Funktion ja wie gesagt S_OK zurückgibt.



  • Also tatsächlich sind alle drei Parameter auf NULL gesetzt... Die Frage ist jetzt wieso.

    ...
      ShowWindow(wD_hwnd, nCmdShow);
    
      resultDEBUG = dxobj.wD_initD3D
      (
        wD_hwnd, 
        wD_swapchain, 
        wD_dev, 
        wD_devcon, 
        1, 
        1
      ); // <--
    
      if(resultDEBUG == S_OK) MessageBox(wD_hwnd, L"S_OK", L"OK", MB_OK);
    
      if(wD_swapchain == NULL) MessageBoxA(wD_hwnd, "wD_swapchain == NULL", "ERROR", MB_OK);
      if(wD_dev == NULL) MessageBoxA(wD_hwnd, "wD_dev == NULL", "ERROR", MB_OK);
      if(wD_devcon == NULL) MessageBoxA(wD_hwnd, "wD_devcon == NULL", "ERROR", MB_OK);
    
      while(1)
      {
        if(PeekMessage(&wD_msg, NULL, 0, 0, PM_REMOVE))
        {
          TranslateMessage(&wD_msg);
          DispatchMessage(&wD_msg);
        }
        else
        {
    
        }
    
        if(wD_msg.message == WM_QUIT) break;
    }
    
      dxobj.~wDC_directx();
      return wD_msg.wParam;
    }
    


  • dxobj.~wDC_directx(); <-- Fehler
    Vielleicht nicht der Fehler den du suchst, aber auf jeden Fall ein Fehler.



  • resultDEBUG = dxobj.wD_initD3D
      (
        wD_hwnd,
        wD_swapchain,
        wD_dev,
        wD_devcon,
        1,
        1
      ); // <--
    

    Die Methode wD_initD3D ändert doch überhaupt nicht die 3 Zeiger, dass die Methode S_OK liefert, braucht überhaupt keine Aussage über die 3 Zeiger machen.
    Die 3 Zeiger müssen also, wenn du den kompletten Codeteil gezeigt hast, schon vorher NULL gewesen sein, die Methode jedenfalls ändert wie gesagt die Zeiger nicht (zumindest nicht für die Deklaration, die du gezeigt hast)



  • Huch,

    ich hab tatsächlich nur den Methodenaufruf gezeigt. Die Methode selbst gar nicht. Die ist ja in der .dll definiert.

    HRESULT wDC_directx::wD_initD3D
    (
      HWND hwnd, 
      IDXGISwapChain * wD_swapchain, 
      ID3D11Device * wD_dev, 
      ID3D11DeviceContext * wD_devcon,
      UINT bbuffer,
      bool windowed
    )
    {
      HRESULT result;
      DXGI_SWAP_CHAIN_DESC wD_scd;
    
      ZeroMemory(&wD_scd, sizeof(DXGI_SWAP_CHAIN_DESC));
    
      wD_scd.BufferCount			= bbuffer;                                    
      wD_scd.BufferDesc.Format	= DXGI_FORMAT_R8G8B8A8_UNORM;     
      wD_scd.BufferUsage			= DXGI_USAGE_RENDER_TARGET_OUTPUT;      
      wD_scd.OutputWindow			= hwnd;                                
      wD_scd.SampleDesc.Count		= 4;                               
      wD_scd.Windowed				= windowed;
    
      result = D3D11CreateDeviceAndSwapChain
      (
        NULL,
        D3D_DRIVER_TYPE_HARDWARE,
        NULL,
        NULL,
        NULL,
        NULL,
        D3D11_SDK_VERSION,
        &wD_scd,
        &wD_swapchain,
        &wD_dev,
        NULL,
        &wD_devcon
      );
    
      return result;
    }
    

    Dort werden alle drei Zeiger verarbeitet. Hoffe ich zumindest...


Log in to reply