Bekomme Memory Leak nicht weg



  • DerMitDemBildTanzt schrieb:

    Warum lädst du das bild jedes mal bei WM_PINT neu? Das ändert sich doch nicht.

    Das kann man ruhig so machen...Man muss halt abwägen zwischen Speicherverbrauch und Performance...



  • CodeFinder schrieb:

    1. Unter WM_PAINT wird i.d.R. NUR gezeichnet...Du zeichnest nicht!
    2. Man sollte auf goto-Marken IMMER verzichten!
    3. Das memset kannste dir sparen, BeginPaint füllt die Struktur für dich...
    4. Das hier ist doppel gemoppelt:

    EndPaint( hDlgExcWin, &ps );
    ReleaseDC( hDlgExcWin, hDC );
    

    Denn EndPaint gibt den DC schon frei...BTW: Du kannst dir die Variable hDC auch sparen... ➡ ps.hdc tuts auch 😉 .

    Zu 1.: Ich zeiche im gekürzten Beispiel nicht, sonst schon!
    Zu 2.: Warum, wird mein Code durch diese Anwenden so unleserlich?
    Zu 3.: Okay, danke.
    Zu 4.: Okay, danke.

    Was ich vermisse ist Punk 5: So bekommst du dein Memory Leak weg...



  • yogle schrieb:

    Zu 1.: Ich zeiche im gekürzten Beispiel nicht, sonst schon!
    [...]
    Was ich vermisse ist Punk 5: So bekommst du dein Memory Leak weg...

    Du bist n Witzbold, zu musst mir erstmal den Code zeigen, dann kann ich dir auch sagen, wo deine Fehler sind...

    yogle schrieb:

    Zu 2.: Warum, wird mein Code durch diese Anwenden so unleserlich?

    Davon gehe ich aus, JA! Außerdem gehts dabei ja auch um Fehleranfälligkeit.
    BTW: Das ist übrigens schlechter Programmier-Stil, man kann das auch alles ohne Sprungmarken lösen.



  • CodeFinder schrieb:

    Du bist n Witzbold, zu musst mir erstmal den Code zeigen, dann kann ich dir auch sagen, wo deine Fehler sind...

    Achso und auf welchen Code hast du geschaut als du meine Fehler "analysiert" hast?

    Ich habe doch im ersten Post den meiner Ansicht nach betroffenen Code gepostet! Wenn dort kein Memory Leak vohanden sein sollte,
    muss es an etwas anderem liegen ➡ ich poste mehr Code.



  • yogle schrieb:

    Achso und auf welchen Code hast du geschaut als du meine Fehler "analysiert" hast?

    LOL, auf das Snippet da oben. Das waren aber nur allgemeine Fehler, die du sowieso gemacht hast, mit dem MemLeak haben die aber nix zu tun...Das ist aber eigentlich klar, da DU JA NICHTS ZEICHNEST (-> in deinem Snippet)!

    yogle schrieb:

    ➡ ich poste mehr Code.

    Und Wann? 😃



  • BOOL CALLBACK ExcWinDlgProc( HWND hDlgExcWin,
    							 UINT uiMsg,
    							 WPARAM wParam,
    							 LPARAM lParam )
    {
    	HBRUSH	hBrushStatic = NULL;
    	RECT	rc;
    
    	memset( &rc, 0, sizeof(RECT));
    
    	switch( uiMsg )
    	{
    		case WM_PAINT:
    		{
    			PAINTSTRUCT	ps;
    			HDC			hDC				= NULL;
    			HRGN		hRgn			= NULL;
    			HBRUSH		hBrush			= NULL;
    			HWND		hWndStatic		= NULL;
    			HBITMAP		hBitmapError	= NULL;
    
    			memset( &ps, 0, sizeof(ps));
    			memset( &rc, 0, sizeof(rc));
    
    			hDC = BeginPaint( hDlgExcWin, &ps );
    			{
    				// Den weißen unteren Rand zeichen
    				hBrush = CreateSolidBrush( RGB(255,255,255));
    				if( hBrush == NULL )
    					goto Cleanup;
    
    				if( GetClientRect( hDlgExcWin, &rc )) 
    				{
    					// Abstand von Unten
    					rc.top = rc.bottom - 48;
    
    					hRgn = CreateRectRgnIndirect( &rc );
    					if( hRgn == NULL )
    						goto Cleanup;
    
    					FillRgn( hDC, hRgn, hBrush );
    				}
    
    				// "Fehler" Bitmap laden
    				hBitmapError = (HBITMAP)LoadImage( (HINSTANCE)ModuleFromAddress( SetCaption ), MAKEINTRESOURCE(IDB_BITMAPERROR), 
    													IMAGE_BITMAP, 0, 0, LR_DEFAULTCOLOR );
    
    				if( hBitmapError == NULL )
    					goto Cleanup;
    
    				// Error Bitmap anzeigen
    				hWndStatic = GetDlgItem( hDlgExcWin, IDC_EXCSTATIC );
    				if( hWndStatic == NULL )
    					goto Cleanup;
    
    				SendMessage( hWndStatic, STM_SETIMAGE, (WPARAM)IMAGE_BITMAP, (LPARAM)(HANDLE)hBitmapError );
    
    				Cleanup:
    				EndPaint( hDlgExcWin, &ps );
    				ReleaseDC( hDlgExcWin, hDC );
    
    				DeleteObject( hRgn );
    				DeleteObject( hBrush );
    				DeleteObject( hBitmapError );
    			}
    		}
    		break;
    
    		case WM_CTLCOLORSTATIC:
    		{
    			if( (HWND)lParam == GetDlgItem( hDlgExcWin, IDC_SENDBUGREPORT ))
    			{
    				SetBkMode( (HDC)wParam, TRANSPARENT );
    				hBrushStatic = CreateSolidBrush( RGB(255,255,255));	// Weiß
    			}
    			else
    			{
    				SetBkMode( (HDC)wParam, TRANSPARENT );
    				hBrushStatic = (HBRUSH)(COLOR_BTNFACE + 1);	// Standtartgrau
    			}
    			return (BOOL)hBrushStatic;
    		}
    		break;
    
    		case WM_INITDIALOG:
    		{
    			HWND hWndDlgItem = NULL;
    
    			// Überschrift dem Dateinamen anpassen
    			SetCaption( hDlgExcWin, false );
    
    			// SendBugReport Häckchen setzen
    			CheckDlgButton( hDlgExcWin, IDC_SENDBUGREPORT, BST_CHECKED );
    
    			// Button Continue nach Situation anpassen
    			if( dwFlag != 0 )
    			{
    				hWndDlgItem = GetDlgItem( hDlgExcWin, IDC_CONTINUE );
    				if( hWndDlgItem != NULL )
    					EnableWindow( hWndDlgItem, FALSE );
    			}
    		}
    		break;
    
    		// Kommandomessages
    		case WM_COMMAND:
    		{
    			if( lParam != 0 )
    			{
    				// Kommandomessages wie z.B. von einem Button
    				switch( wParam )
    				{
    					case IDC_CONTINUE:
    					{
    						// Nur reagieren wenn der Button Continue aktiv ist 
    						if( dwFlag == 0 )
    							lReturn = EXCEPTION_CONTINUE_EXECUTION;
    						else
    							break;
    
    						if( IsDlgButtonChecked( hDlgExcWin, IDC_SENDBUGREPORT ) == BST_CHECKED )
    						{
    							if( SendBugReport( hDlgExcWin ))
    								EndDialog( hDlgExcWin, 0 );		// Nur das ExcWin-Fenster beenden wenn Senden erfolgreich war
    							else
    								break;
    						}
    					}
    					break;
    
    					case IDC_RESTART:
    					{
    						CStdString			strCurrentProcess;
    						STARTUPINFO			st;
    						PROCESS_INFORMATION	pi;
    
    						memset( &st, 0, sizeof(st));
    						memset( &pi, 0, sizeof(pi));
    						st.cb = sizeof(st);
    						strCurrentProcess.Empty();
    
    						if( IsDlgButtonChecked( hDlgExcWin, IDC_SENDBUGREPORT ) == BST_CHECKED )
    						{
    							if( SendBugReport( hDlgExcWin ))
    								EndDialog( hDlgExcWin, 0 );		// Nur das ExcFenster beenden wenn Senden erfolgreich war
    							else
    								break;
    						}
    
    						// Prozessstartup Informationen auslesen
    						GetStartupInfo( &st );
    
    						// TODO: Hier noch auslesen, was es für ein Prozess ist (Konsole, GUI) da GetCommandLine... (Doku)
    						if( GetModuleFileName( NULL, strCurrentProcess.GetBuffer( UNICODE_STR_LEN +1 ), UNICODE_STR_LEN ) != 0 )
    							CreateProcess( strCurrentProcess.c_str(), GetCommandLine(), NULL, NULL, false, 0, NULL, NULL, &st, &pi );
    
    						lReturn = EXCEPTION_EXECUTE_HANDLER;
    						EndDialog( hDlgExcWin, 0 );
    					}
    					break;
    
    					case IDC_CLOSE:
    					{
    						if( IsDlgButtonChecked( hDlgExcWin, IDC_SENDBUGREPORT ) == BST_CHECKED )
    						{
    							if( SendBugReport( hDlgExcWin ))
    								EndDialog( hDlgExcWin, 0 );		// Nur das ExcFenster beenden wenn Senden erfolgreich war
    							else
    								break;
    						}
    
    						lReturn = EXCEPTION_EXECUTE_HANDLER;
    						EndDialog( hDlgExcWin, 0 );
    					}
    					break;
    
    					case IDC_SHOWBUGREPORT:
    					{
    						// Den BugReport erst anzeigen, wenn er fertig erstellt ist
    						EnterCriticalSection( &g_lpCriticalSect );
    						if( g_bBugReportReady )
    							DialogBoxParam( (HINSTANCE)ModuleFromAddress( SetCaption ), MAKEINTRESOURCE(IDD_BUGREPORT), hDlgExcWin, 
    											BugReportProc, 0 );
    						else
    							MessageBox( NULL, _T("Bugreport isn't complete, please wait!"), _T("Please wait"), MB_OK | MB_ICONINFORMATION );	// OUT:
    
    						LeaveCriticalSection( &g_lpCriticalSect );
    					}
    					break;
    
    					default:
    						break;
    				}
    			}
    		}
    		break;
    
    		case WM_DESTROY:
    			DeleteObject( hBrushStatic );
    		break;
    
    		// Das X ober rechts
    		case WM_CLOSE:
    		{
    			lReturn = EXCEPTION_EXECUTE_HANDLER;
    			EndDialog( hDlgExcWin, 0 );
                return true;
    		}
    		break;
    
    		default:
    			return false;
    	}
    	return true;
    }
    

    So das ist die komplette Callback Routine, wie sie derzeit aussieht, leider noch ohne die von dir angesprochenen Fehlern ausgemerzt zu haben :p



  • Und? Was ist jetzt? Jetzt habe ich schon den gesamten Code gepostet und mir kann erst keiner helfen. 😞



  • hBrushStatic = CreateSolidBrush( RGB(255,255,255));    // Weiß
    

    das ist schonmal ein gdi leak



  • Hmm stimmt, danke. Ich dachte das DeleteObject bei WM_DESTROY reicht. Stimmt aber nicht. Aber wie sollte man das ändern? Ich muss ja den Brush zurückgeben.

    Der massive Speicherverbrauch beim neuzeichen ändert sich dadurch auch nicht.
    Er verschwindet erst, wenn ich

    SendMessage( hWndStatic, STM_SETIMAGE, (WPARAM)IMAGE_BITMAP, (LPARAM)(HANDLE)hBitmapError );
    

    weglasse. Wie könnte ich das ändern?

    Edit: Habs jetzt hinbekommen, der kleine Speicherleak mit CreateSolidBrush bleibt allerdings noch. Hat da jemand eine Idee?



  • Also erstmal das zu deinem 'hBrushStatic' :

    static HBRUSH hBrushStatic;
    
    switch(uiMsg)
    {
    
    WM_CREATE:
    hBrushStatic = CreateSolidBrush(...);
    break;
    
    WM_XXX:
    // Benutzen...
    
    WM_DESTROY:
    DeleteObject(hBrushStatic);
    break;
    
    }
    

    Boah dieser Code ist....naja egal... Also ich habe erstmal keine Lust, zu prüfen, ob wegen der goto Marken möglichweise 8versehentlich) irgend etwas übersprungen wird...musste selbst gucken -> Hab dir ja gesagt das man das so nicht machen sollte.

    Das EndPaint den DC schon freigibt (und damit ReleaseDC überflüssig ist) sagte ich auch schon...

    Wird nach einem Klick auf schließen überhaupt dein WM_DESTROY-Handler erreicht? Du machst den Dialog ja schon unter WM_CLOSE mit EndDialog platt :p (Da wär ich mir nit ganz sicher).

    PS_1: Da du nur ein weißen Brush erstellst kannst du auch einfach GetStockObject(WHITE_BRUSH) nehmen. Den Handle brauchste nämlich nicht freigeben.

    PS_2: Eine Dialog-Prozedur hat neuerdings INT_PTR als Return-Typ. Das setzt allerdings eine geupdatete PSDK voraus.


Anmelden zum Antworten