Bekomme Memory Leak nicht weg
-
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
.
-
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 ichSendMessage( 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.