Absturz beim beenden von pixel plotting



  • Hallo!

    Es wäre sehr nett wenn ihr folgenden Code eben in eine Win32-Anwendung kopieren und compilieren+ausführen würdet, nicht von der Länge abschrecken lassen, ist leider zwangsweise so das der Code so lang sein muss 😞

    // dxguid.lib ddraw.lib includen
    #define WIN32_LEAN_AND_MEAN // MFC und selten genutzte Objekte nicht includen
    
    // Include Dateien
    #include <windows.h>
    #include <mmsystem.h> // Sound
    #include <stdlib.h>   // Randomizefunktion
    #include <ddraw.h>    // DirectDraw
    
    // Defines
    #define WINDOW_CLASS_NAME "WINCLASS1"
    #define WINDOW_HEIGHT 400
    #define WINDOW_WIDTH  400
    
    // Fenstereigenschaften
    #define SCREEN_WIDTH  1024 
    #define SCREEN_HEIGHT  768
    #define SCREEN_BPP       8 
    
    // Funktionsprototypen
    int Game_Init(void),Game_Shutdown(void);
    void Game_Main(void),Create_Surface(void), Create_Palette(void), Plot_Pixel(void);
    
    // Global
    bool                 running            = false;
    HWND                 main_window_handle = NULL;
    LPDIRECTDRAW7        lpdd7              = NULL;
    LPDIRECTDRAWSURFACE7 lpddsprimary       = NULL; // Pointer auf die Oberfläche
    DDSURFACEDESC2       ddsd;
    LPDIRECTDRAWPALETTE  lpddpal            = NULL;
    PALETTEENTRY         palette[256];
    char buffer[100];
    
    // Window's Procedure Funktion ///////////////////////////////////////////////
    LRESULT WINAPI WindowProc(HWND hwnd, UINT msg, WPARAM wparam, LPARAM lparam)
    {
    	PAINTSTRUCT		ps;  // Wird in WM_PAINT genutzt
    	HDC				hdc; // Handle zu einem best. Fenster
    
    	switch(msg)
    	{
    	case WM_CREATE:
    		{
    			return(0);
    		}break;
    
    	case WM_PAINT:
    		{
    			hdc = BeginPaint(hwnd,&ps);
    			EndPaint(hwnd,&ps);
    			return(0);
    		}break;
    
    	case WM_DESTROY:
    		{
    			Game_Shutdown();
    			return(0);
    		}break;
    
    	default:break;
    	}
    
    	// Sonstige Messages verarbeiten (Default Window Processes)
    	return(DefWindowProc(hwnd, msg, wparam, lparam));
    }
    
    // WINMAIN ///////////////////////////////////////////////////////////////////
    int WINAPI WinMain(HINSTANCE hinstance, HINSTANCE hPrevInstance, LPSTR lpcmdline, int ncmdshow)
    {
    	WNDCLASSEX winclass; // Speichert die Klasse die erschaffen wird
    	MSG        msg;
    
    	// Die Fensterklassenstruktur
    	winclass.cbSize = sizeof(WNDCLASSEX);
    	winclass.style = CS_DBLCLKS | CS_OWNDC | CS_HREDRAW | CS_VREDRAW;
    	winclass.lpfnWndProc = WindowProc;
    	winclass.cbClsExtra = 0;
    	winclass.cbWndExtra = 0;
    	winclass.hInstance = hinstance;
    	winclass.hIcon = LoadIcon(NULL, IDI_WINLOGO);
    	winclass.hCursor = LoadCursor(NULL, IDC_ARROW);
    	winclass.hbrBackground = (HBRUSH)GetStockObject(BLACK_BRUSH);
    	winclass.lpszMenuName = NULL;
    	winclass.lpszClassName = WINDOW_CLASS_NAME;
    	winclass.hIconSm = LoadIcon(NULL, IDI_WINLOGO);
    
    	// Fensterklasse bei Windows regestrieren
    	if(!RegisterClassEx(&winclass))
    		return(0);
    
    	// Fenster erschaffen
    	if(!(main_window_handle = CreateWindowEx(
    		   NULL, 
    		   WINDOW_CLASS_NAME, 
    		   "Direct Draw Initialisierung",
    		   WS_POPUP | WS_VISIBLE,
    		   0,0,							// Startposition
    		   WINDOW_HEIGHT,WINDOW_WIDTH,  // Fenstergröße
    		   NULL,						// Handle geht an das Desktop
    		   NULL,
    		   hinstance, 
    		   NULL)))						// Zusätzliche Parameter
    		   return(0);
    
    	Game_Init();
    
    	// Hauptschleife
    	while(running)
    	{
    		if(PeekMessage(&msg,NULL,0,0,PM_REMOVE))
    		{
    			if(msg.message == WM_QUIT)
    				break;
    
    		TranslateMessage(&msg); // Tastenbetätigungen übersetzen
    		DispatchMessage(&msg);  //         "          an Window Processer senden
    		}
        	Game_Main();
    	}
    
        Game_Shutdown();
    
    	return(msg.wParam);
    }
    
    // Game_Init() /////////////////////////////////////////////////////////////////////
    int Game_Init()
    {
    	if(FAILED(DirectDrawCreateEx(NULL, (void **)&lpdd7, IID_IDirectDraw7, NULL)))
    		MessageBox(main_window_handle, "Fehler bei DirectDrawCreateEx in Game_Init()!", "Fehler", MB_OK | MB_ICONERROR);
    
    	if(FAILED(lpdd7->SetCooperativeLevel(main_window_handle, DDSCL_FULLSCREEN | DDSCL_ALLOWMODEX | DDSCL_EXCLUSIVE | DDSCL_ALLOWREBOOT)))
    		MessageBox(main_window_handle, "Fehler bei SetCooperativeLevel in Game_Init()!", "Fehler", MB_OK | MB_ICONERROR);
    
    	if(FAILED(lpdd7->SetDisplayMode(SCREEN_WIDTH,SCREEN_HEIGHT,SCREEN_BPP, 0, 0)))
    		MessageBox(main_window_handle, "Fehler bei SetDisplayMode in Game_Init()!", "Fehler", MB_OK | MB_ICONERROR);
    
        Create_Surface();
    	Create_Palette();
    
    	running = true;
    //	MessageBox(main_window_handle, "Game_Init() wurde erfolgreich durchlaufen", "Hinweis", MB_OK | MB_ICONINFORMATION);	
    	return(0);
    }
    
    // Create_Surface() ////////////////////////////////////////////////////////////////////////
    void Create_Surface()
    {
    	memset(&ddsd,0,sizeof(ddsd));
    	ddsd.dwSize = sizeof(ddsd);
    	ddsd.dwFlags = DDSD_CAPS;
    	ddsd.ddsCaps.dwCaps = DDSCAPS_PRIMARYSURFACE;
    	if(FAILED(lpdd7->CreateSurface(&ddsd, &lpddsprimary, NULL)))
    		MessageBox(main_window_handle, "Fehler bei lpdd7->CreateSurface() in Create_Surface()!", "Fehler", MB_OK | MB_ICONERROR);
    }
    
    // Create_Palette() /////////////////////////////////////////////////////////////////////
    void Create_Palette()
    {
     for(int i=1; i<=255; ++i)
     {
    	 palette[i].peRed   = rand()%256;
    	 palette[i].peGreen = rand()%256;
    	 palette[i].peBlue  = rand()%256;
    	 palette[i].peFlags = PC_NOCOLLAPSE;
     }
    
     palette[0].peRed   = 0;
     palette[0].peGreen = 0;
     palette[0].peBlue  = 0;
     palette[0].peFlags = PC_NOCOLLAPSE;
    
     palette[255].peRed   = 255;
     palette[255].peGreen = 255;
     palette[255].peBlue  = 255;
     palette[255].peFlags = PC_NOCOLLAPSE;
    
     if(FAILED(lpdd7->CreatePalette(DDPCAPS_8BIT | DDPCAPS_ALLOW256 | DDPCAPS_INITIALIZE, palette,&lpddpal, NULL)))
        MessageBox(main_window_handle, "Fehler bei lpdd7->CreatePalette() in Create_Palette()!", "Fehler", MB_OK | MB_ICONERROR);
    
     if(FAILED(lpddsprimary->SetPalette(lpddpal)))
    	 MessageBox(main_window_handle, "Fehler bei lpddsprimary->SetPalette() in Create_Palette()!", "Fehler", MB_OK | MB_ICONERROR); 
    }
    
    // Plot_Pixel /////////////////////////////////////////////////////////////////////
    void Plot_Pixel()
    {
     if(FAILED(lpddsprimary->Lock(NULL, &ddsd, DDLOCK_SURFACEMEMORYPTR | DDLOCK_WAIT, NULL)))
    	 MessageBox(main_window_handle, "Fehler bei lpddsprimary->Lock() in Create_Palette()!", "Fehler", MB_OK | MB_ICONERROR);
    
     int mempitch = (int)ddsd.lPitch;
     UCHAR *video_buffer = (UCHAR *)ddsd.lpSurface;
     for(int i=0; i<=1000; ++i)
     {
    	 UCHAR color = rand()%256;
    	 int x = rand()%SCREEN_WIDTH;
    	 int y = rand()%SCREEN_HEIGHT;
    	 video_buffer[x+y*mempitch] = color;
     }
     lpddsprimary->Unlock(NULL);
     Sleep(30);
    }
    // Game_Main() /////////////////////////////////////////////////////////////////////
    void Game_Main()
    {
     Plot_Pixel();
    }
    
    // Game_Shutdown() /////////////////////////////////////////////////////////////////
    int Game_Shutdown()
    {
     running = false;
     if(lpddpal)
     {
       lpddpal->Release();
       lpddpal = NULL;
       MessageBox(main_window_handle, "Palette freigegeben!", "Hinweis", MB_OK | MB_ICONINFORMATION);
     }
    
     if(lpddsprimary)
     {
    	 lpddsprimary->Release();
    	 lpddsprimary = NULL;
    	 MessageBox(main_window_handle, "lpddsprimary freigegeben!", "Hinweis", MB_OK | MB_ICONINFORMATION);
     }
    
     if(lpdd7)
       {
    	 lpdd7->Release();
    	 lpdd7 = NULL;
       }
    
     MessageBox(main_window_handle, "Game_Shutdown() wurde erfolgreich durchlaufen", "Hinweis", MB_OK | MB_ICONINFORMATION);
     PostQuitMessage(0);
     return(0);
    }
    

    Hier die Erklärung:

    Das Winapifenster wird erzeugt und game_init wird als erstes aufgerufen um ddraw zu initialisieren. Soweit so gut, nun soll game_main immer wieder aufgerufen werden, solange running == true ist, jeder der André LaMothe's Buch gelesen hat wird den Aufbau sofort wieder erkennen.
    Wenn das Fenster zerstört werden soll wird game_shutdown aufgerufen und soll dafür sorgen das game_main nicht mehr ausgeführt wird da running auf false gesetzt wird. Allerdings macht die schleife anscheinden doch noch nen aufruf, denn das Programm schmiert ganz am ende nochmal ab weil ein pixel geplottet werden soll

    video_buffer[x+y*mempitch] = color;

    Und dann stürzt er ab, ich meine es liegt daran das er game_main halt ein weiteres mal ausführt. Wie kann ich das unterdrücken. Ich bin echt ratlos 😞
    Ab und zu kommt auch die Meldung das er
    "lpddsprimary->Lock()" nicht ausführen konnte und er stürzt wieder beim plotten ab, ist das bei euch auch so?

    Wäre nett wenn ihr das mal bei euch testet, ich hoffe darauf das jemand weiß worans liegt.

    gruß

    Delryn



  • Du solltest bevor du Lock aufrufst deine DDSURFACEDESC2 initialisieren,
    sprich:

    memset(&ddsd,0,sizeof(ddsd));
    ddsd.dwSize = sizeof(ddsd);
    

    Lock prüft nämlich beim Aufruf dwSize!
    Normalerweise ist dann Lock auch nicht erfolgreich, auf jeden Fall aber wird ddsd nicht mit gueltigen Daten gefüllt, also ist weder der Surface Pointer noch lpPitch gültig und du schreibst ins Niemandsland.

    Viele Grüße
    Fischi


Anmelden zum Antworten