[WinAPI] Wyciek pamięci w funkcji WndProc

0

Mam pewien problem, ponieważ mój program w WinAPI po pewnym czasie użytkowania się zawiesza, odkryłem, że ma to związek z wyciekiem pamięci. W chwili uruchomienia program zajmuje około 2mb w pamięci, a potem systematycznie ilość zajmowanej pamięci się zwiększa - dzieje się tak, kiedy w oknie ruszam myszą, kiedy kursor jest nieruchomy, przyrost pamięci jest dużo mniejszy.

W mojej funkcji WndProc mam następujące zmienne:

static char C[100];
	static LOGFONT lfms1 = logfont(24,0,"A");
	static LOGFONT lfms2 = logfont(16,0,"A");
	static LOGFONT lfms = logfont(20,0,"C");
	static RECT rec1 = {0,37,600,84};
	static RECT rec2 = {0,0,600,34};
	static RECT rec3 = {0,87,600,150};
	HDC hdc = GetDC(hwnd);
	static PAINTSTRUCT ps;

a obsługa komunikatu WM_PAINT wygląda tak:

case WM_PAINT:
		InvalidateRect(hwnd,0,FALSE);
		hdc = BeginPaint(hwnd,&ps);
		FillRect(hdc,&rec1,CreateSolidBrush(0xEFEFEF));
		FillRect(hdc,&rec2,CreateSolidBrush(0xFFFFFF));
		FillRect(hdc,&rec3,CreateSolidBrush(0xFFFFFF));
		sprintf_s(C,100,"Blablabla");
		text(hdc,lfms1,navy,white);
		TextOut(hdc,12,6,C,strlen(C));
		sprintf_s(C,100,"Blablabla");	
		text(hdc,lfms2,navy,white);
		TextOut(hdc,12,96,C,strlen(C));
		sprintf_s(C,100,"Blablabla");
		text(hdc,lfms2,navy,white);
		TextOut(hdc,476,96,C,strlen(C));
		MoveToEx(hdc,0,35,0);
		LineTo(hdc,600,35);
		MoveToEx(hdc,0,85,0);
		LineTo(hdc,600,85);
		GetFocus();
		EndPaint(hwnd,&ps);
		break;

Kiedy usunę zmienne i obsługę WM_PAINT problem znika - pamięć nie rośnie. Da się to w jakiś sposób 'naprawić'? Zmienne są przecież staticami, więc nie powinno się tak dziać, chyba, że ja coś mylę...

0

Trzykrotnie wołany CreateSolidBrush - tworzysz obiekt GDI, ale go nie zwalniasz, w ten sposób masz nie tyle wyciek pamięci co zasobów, jeszcze groźniejszy. Na każde tworzenie obiektu GDI musi przypadać DeleteObject, z pominięciem tych przekazanych do SelectObject, wtedy zazwyczaj niszczysz to, co zwróciła funkcja. Poza tym używanie InvalidateRect z obsługi WM_PAINT względem aktualnie obsługiwanego okna to raczej średni pomysł. Jeżeli potrzebujesz tego ze względu na tło to lepiej sięgnąć po RedrawWindow z odpowiednimi flagami.

0

Dziękuję bardzo za cenne informacje :) zdaję sobie sprawę, że niektóre rzeczy tam są zrobione 'na szybko' jak to Invalidate i Brushe, ale program jest w trakcie dopieszczania :)

Wyczytałem, że oprócz GetDC(...) trzeba później stosować ReleaseDC(...) i tak też robię. W oknach, w których nie mam obsługi komunikatu WM_MOUSEMOVE udało mi się zatrzymać wyciek, ale w oknie, gdzie obsługuję ten komunikat problem dalej istnieje : / Sprawdziłem, czy dotyczy to tego komunikatu i po usunięciu poniższego kodu dla obsługi WM_MOUSEMOVE problem znika, a z nim - pamięć wycieka przy ruszaniu myszą, więc coś tam jest popsute, ale mimo wielu prób nie mogę dojść do tego co...

case WM_MOUSEMOVE: 
			hdc=GetDC(hwnd);
			msx=LOWORD(lPar);  msy=HIWORD(lPar);
			pixcol = GetPixel(hdc, msx, msy);
			cr = GetRValue(pixcol);
			sprintf_s(C,100,"%03d",(int)cr);
			text(hdc,lfms,black,lightgray);
			TextOut(hdc,287,354,C,strlen(C));
			TextOut(hdc,400,354,C,strlen(C));
			if(msy>52 && msy<343) {
				if(psx<0){psx=msx;  psy=msy;}
				sprintf_s(C,100,"%03d %03d %4s",msx,msy-54,lbutton?"down":"up");
				text(hdc,lfms,black,lightgray);  
				TextOut(hdc,465,354,C,strlen(C));
				GetFocus();
				MoveToEx(hdc,psx,psy,0);
				if(lbutton) {
					switch(inC[0]) {
						case '0': line(hdc,PS_SOLID,3,black ); break;
						case '1': line(hdc,PS_SOLID,1,black ); break;
					}
					LineTo(hdc,msx,msy);
				}
				psx=msx;  psy=msy;
			}
			ReleaseDC(hwnd, hdc);
			break;

EDIT
Naprowadziłeś mnie - dziękuję! :) text i line to były moje własne funkcje, a w 'text' miałem właśnie SelectObject, ale nie usuwałem go poprzez DeleteObject i dlatego tutaj program miał wyciek :)
Dziękuję jeszcze raz!

0

aaaaa ile razy to widzialem a i tak widze jak Ci co ucza przywiazuja do tego mniejsza wage twierdzac, ze to oczywiste albo sie o tym pozniej powie (i sie nie mowi). I nawet .NET czy Java nie zwalnia nas ot tak z obowiazku niszczenia i czyszczenia po sobie !! Niektorzy nawet mowia (o zgrozo), ze po zamknieciu aplikacji i tak sie wszytsko posprzata.

A i czemu niebezpieczne, to sa zasoby (GDI) powiedzmy niejako wirtualne ale takimi zasobami moze byc sprzet, licencje, dostep do bazy danych.
Ostatni przyklad - brak niszczenia przy zle skonfigurowanym serwerze MySQL i zle napisanej aplikacji doprowadzil do zuzycia zasobow - polaczenia -, czyli nastepny user nie mogl sie podlaczyc. A zasoby wyczerpala aplikacja po kilku minutowym uzywaniu jej ...

1 użytkowników online, w tym zalogowanych: 0, gości: 1