Detecting memory leaks -> episode 4

Hi,
I am new to gamedev and starting by watching these episodes. In episode 4, we create a basic window. When I check my memory usage of my program, it s around 220MB. I thought it should be around 30-50 MB. Can anyone help where I made a mistake? Here is my code:


  1
  2
  3
  4
  5
  6
  7
  8
  9
 10
 11
 12
 13
 14
 15
 16
 17
 18
 19
 20
 21
 22
 23
 24
 25
 26
 27
 28
 29
 30
 31
 32
 33
 34
 35
 36
 37
 38
 39
 40
 41
 42
 43
 44
 45
 46
 47
 48
 49
 50
 51
 52
 53
 54
 55
 56
 57
 58
 59
 60
 61
 62
 63
 64
 65
 66
 67
 68
 69
 70
 71
 72
 73
 74
 75
 76
 77
 78
 79
 80
 81
 82
 83
 84
 85
 86
 87
 88
 89
 90
 91
 92
 93
 94
 95
 96
 97
 98
 99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
static BITMAPINFO btmpnfo;
static void* bitmapMemory;
static int bh;
static int bw;
static int  xoffset = 0;
static int yoffset = 0;
static bool running;
static int bytesPerPixel = 4;

void
renderW(int xoffset, int offset) {
	uint8* row = (uint8*)bitmapMemory;
	int pitch = bytesPerPixel * bw;
	for (int x = 0; x < bh; x++) {
		uint32* pixel = (uint32*)row;				//XX BB GG RR 
										// each of them 1 byte=8bit
		for (int y = 0; y < bw; y++) {
			uint8 green =x+xoffset ;
			uint8 blue = y;
			*pixel = (green << 8) + blue;
			pixel++;
		}
		row += pitch;
	}

}

void
RUpdateWindow(HDC hdc, RECT* WRect, int left, int top, int right, int bottom) {
	int wtop = WRect->top;
	int wbottom = WRect->bottom;
	int wleft = WRect->left;
	int wright = WRect->right;
	StretchDIBits(
		hdc,
//		left, top, right - left, bottom - top,
//		left, top, right - left, bottom - top,
		0, 0, bw, bh,
		0, 0, wright - wleft, wbottom - wtop,
		bitmapMemory,
		&btmpnfo,
		DIB_RGB_COLORS, SRCCOPY
	);
}



void
ResizeDIBSection(int w, int h) {
	bytesPerPixel = 4;
	int bitmapMemorySizeNeeded = bytesPerPixel * w * h;

	if (!bitmapMemory) {
		VirtualFree(bitmapMemory, 0, MEM_RELEASE);
	}
	bh = h;
	bw = w;

	btmpnfo.bmiHeader.biSize = sizeof(btmpnfo.bmiHeader);
	btmpnfo.bmiHeader.biWidth = w;
	btmpnfo.bmiHeader.biHeight = -h;
	btmpnfo.bmiHeader.biPlanes = 1;
	btmpnfo.bmiHeader.biBitCount = 32;
	btmpnfo.bmiHeader.biCompression = BI_RGB;


	bitmapMemory = VirtualAlloc(0, bitmapMemorySizeNeeded, MEM_COMMIT, PAGE_READWRITE);
}



LRESULT CALLBACK CallWindowProc(
	HWND    hWnd,
	UINT    Msg,
	WPARAM  wParam,
	LPARAM  lParam
) {
	switch (Msg) {
	case WM_SIZE: {
		RECT ClientRect;
		GetClientRect(hWnd, &ClientRect);
		int h = ClientRect.bottom - ClientRect.top;
		int w = ClientRect.right - ClientRect.left;
		ResizeDIBSection(w, h);
		xoffset++;
		yoffset++;
	}break;
	case WM_DESTROY: {
		PostQuitMessage(0);
		return 0;
	}break;

	case WM_PAINT: {
		PAINTSTRUCT ps;
		HDC hdc = BeginPaint(hWnd, &ps);
		int x = ps.rcPaint.left;
		int y = ps.rcPaint.top;
		int y2 = ps.rcPaint.bottom;
		int x2 = ps.rcPaint.right;
		RECT ClientRect;
		GetClientRect(hWnd, &ClientRect);
		RUpdateWindow(hdc, &ClientRect, x, y, x2, y2);
	}break;

	case WM_CLOSE: {
		if (MessageBox(hWnd, L"Are You Sure?", L"Quit", MB_OKCANCEL) == IDOK) {
			DestroyWindow(hWnd);
		}
	}break;
	default: {
		return DefWindowProc(hWnd, Msg, wParam, lParam);
	}
	}
}
int WINAPI WinMain(HINSTANCE H,
	HINSTANCE prevH,
	LPSTR cmdLine,
	int cmdShow) {

	WNDCLASS w = { };
	w.lpfnWndProc = CallWindowProc;
	w.hInstance = H;
	w.lpszClassName = L"Name of Application";
	RegisterClass(&w);
	HWND winHandle = CreateWindowEx(
		0,
		L"Name of Application",
		L"Name of Window",
		WS_OVERLAPPEDWINDOW,
		CW_USEDEFAULT,
		CW_USEDEFAULT,
		CW_USEDEFAULT,
		CW_USEDEFAULT,
		0,
		0,
		H,
		0);
	if (winHandle == NULL) return 1;
	ShowWindow(winHandle, cmdShow);
	UpdateWindow(winHandle);
	MSG message = { };
	if (winHandle) {
		running = true;

		while (running) {
			xoffset=yoffset;
			yoffset++;
			while (PeekMessage(&message, NULL, 0, 0, PM_REMOVE)) {
				if (message.message == WM_QUIT) running = false;
				TranslateMessage(&message);
				DispatchMessageW(&message);
			}
			RECT ClientRect;
			GetClientRect(winHandle, &ClientRect);
			HDC hdc = GetDC(winHandle);
			renderW(xoffset, yoffset);
			RUpdateWindow(hdc, &ClientRect, 0, 0, 
				ClientRect.right, ClientRect.bottom);
			ReleaseDC(winHandle, hdc);
		}
	}
	return 0;
}

Edited by Sam on Reason: Initial post
Depending on your system - there might be background programs running that inject into your process doing some stuff (extra keyboard shortcuts, antivirus, etc..). They most likely use memory.

Check in debugger what dll's are loaded into the process. In my case your application uses 15MB of memory and here are DLL's that are loaded: https://i.imgur.com/BzRne04.png

Your CallWindowProc function has few bugs:
1) it does not return any value in some cases, like WM_SIZE, WM_PAINT and WM_CLOSE.
2) no EndPaint call when you do BeginPaint.

Edited by Mārtiņš Možeiko on
There is also a leak with bitmapMemory when resizing the window because the if statement on line 53 is inverted.

VirtualFree is being called when bitmapMemory is null instead of when not null.
Depending on your system - there might be background programs running that inject into your process doing some stuff (extra keyboard shortcuts, antivirus, etc..). They most likely use memory.

Check in debugger what dll's are loaded into the process. In my case your application uses 15MB of memory and here are DLL's that are loaded: https://i.imgur.com/BzRne04.png

Your CallWindowProc function has few bugs:
1) it does not return any value in some cases, like WM_SIZE, WM_PAINT and WM_CLOSE.
2) no EndPaint call when you do BeginPaint.


Hi, thanks for the bugs. I fixed them. I checked the dlls. There were awful lot of them. And I don't quite understand them. But the important thing is the sole window now takes around 3-5 MB of memory. Thanks.

Edited by Sam on
There is also a leak with bitmapMemory when resizing the window because the if statement on line 53 is inverted.

VirtualFree is being called when bitmapMemory is null instead of when not null.


Hi, thanks. Fixed it. Don't know what I was thinking while writing that.

Edited by Sam on