| | |
Memory leak in game
Please support our C++ advertiser: Intel Parallel Studio Home
Thread Solved |
•
•
Join Date: Mar 2008
Posts: 1,460
Reputation:
Solved Threads: 121
Hi
I have a memory leak somewhere in this code but I have no idea where. Can anybody help me out ?
Here is the link to download the poject.
http://www.2shared.com/file/3022171/.../SameGame.html
I have a memory leak somewhere in this code but I have no idea where. Can anybody help me out ?
C++ Syntax (Toggle Plain Text)
#include <windows.h> #include <mmsystem.h> #pragma comment(lib, "winmm.lib") #include <fstream> #include <time.h> #include <cstring> #include "resource.h" using namespace std; const char cn[] = "SameGame"; // ClassName HBITMAP BLUEBMP = LoadBitmap(GetModuleHandle(NULL), MAKEINTRESOURCE(IDB_BLUE1)); HBITMAP GREENBMP = LoadBitmap(GetModuleHandle(NULL), MAKEINTRESOURCE(IDB_GREEN1)); HBITMAP REDBMP = LoadBitmap(GetModuleHandle(NULL), MAKEINTRESOURCE(IDB_RED1)); HBITMAP YELLOWBMP = LoadBitmap(GetModuleHandle(NULL), MAKEINTRESOURCE(IDB_YELLOW1)); HBITMAP BLUEBMP_S = LoadBitmap(GetModuleHandle(NULL), MAKEINTRESOURCE(IDB_BLUE2)); HBITMAP GREENBMP_S = LoadBitmap(GetModuleHandle(NULL), MAKEINTRESOURCE(IDB_GREEN2)); HBITMAP REDBMP_S = LoadBitmap(GetModuleHandle(NULL), MAKEINTRESOURCE(IDB_RED2)); HBITMAP YELLOWBMP_S = LoadBitmap(GetModuleHandle(NULL), MAKEINTRESOURCE(IDB_YELLOW2)); #define EMPTY 0 #define IS_SELECTED(B) (B > 4) #define IS_EMPTY(B) (B == EMPTY) #define SELECTED 8 // 1000 #define BLUE 1 // 0001 #define GREEN 2 // 0010 #define RED 3 // 0011 #define YELLOW 4 // 0100 int width = 15; // Grid Width int height = 15; // Grid Height #define ballSize 30 // Ball Diameter #define ID_DELAY 1 #define ID_DELAY2 2 int score = 0; int tempScore = 0; bool MEGASHIFT = 0; unsigned char grid[100][100]; HPEN pen = CreatePen(PS_SOLID , 0 , RGB(255,255,255)); HPEN panel = CreatePen(PS_SOLID , 0 , RGB(0,0,0)); HDC hdc; HBITMAP bmp; BITMAP bm; PAINTSTRUCT ps; HDC _hdc; HDC _hdcMem; HBITMAP hbmOld; int randNum; int RandomNumber(int high, int low) { return ((rand() % high - low) + low + 1); } int bi; // Ball Index int bc; // Ball count int TB; // SHIFTING TOP BALL int BB; // SHIFTING BOTTOM BALL int RB; // SHIFTING RIGHT BALL int LB; // SHIFTING LEFT BALL UINT _w = width; UINT _h = height; char *_score = new char(); char *_tempscore = new char(); bool idg = 0; void (*delayFunction)(HWND); int GETINTLENGTH(int num) { int curMax = 10; int noOfChs = 1; while (num > curMax) { curMax *= 10; noOfChs++; } return noOfChs; } char *INTTOCHARP(int num) { char *val = new char(); _itoa_s(num, val, GETINTLENGTH(num)+1, 10); return val; } int GET_TRUE_COL(int ball) { return ball ^ SELECTED; } void REMOVEALLSELECTED() { for (int y = 0; y < height; y++) { for (int x = 0; x < width; x++) { if (IS_SELECTED(grid[y][x])) { grid[y][x] = EMPTY; } } } } void UNSELECTALL() { for (int y = 0; y < height; y++) { for (int x = 0; x < width; x++) { if (IS_SELECTED(grid[y][x])) { grid[y][x] ^= SELECTED; } } } } void REPAINT(HWND hwnd) { InvalidateRect(hwnd, NULL, 1); } void NEWGAME(HWND hwnd) { srand((int)time(NULL)); score = 0; tempScore = 0; for (int y = 0; y < height; y++) { for (int x = 0; x < width; x++) { randNum = RandomNumber(4,0); grid[y][x] = randNum; } } REPAINT(hwnd); } void FLOOD(int x, int y, int col) { grid[y][x] |= SELECTED; bc++; if (x >= 1) if (col == (int) grid[y][x-1] && int( grid[y][x-1] ) ^ (int) col == SELECTED) FLOOD(x-1, y, col); if (x <= width-2) if (col == (int) grid[y][x+1] && int( grid[y][x+1] ) ^ (int) col == SELECTED) FLOOD(x+1, y, col); if (y >= 1) if (col == (int) grid[y-1][x] && int( grid[y-1][x] ) ^ (int) col == SELECTED) FLOOD(x, y-1, col); if (y <= height-2) if (col == (int) grid[y+1][x] && int( grid[y+1][x] ) ^ (int) col == SELECTED) FLOOD(x, y+1, col); } void SHIFTALLDOWN() { for (int y = height - 2; y >= 0; y--) { for (int x = 0; x < width; x++) { TB = grid[y][x]; BB = grid[y+1][x]; if (IS_EMPTY(BB) && (!IS_EMPTY(TB))) { grid[y+1][x] = grid[y][x]; grid[y][x] = EMPTY; x--; if (y+1 != height-1) y++; else y = height-2; } } } } void SHIFTALLRIGHT() { for (int y = 0; y < height; y++) { for (int x = width - 2; x >= 0; x--) { LB = grid[y][x]; RB = grid[y][x+1]; if (IS_EMPTY(RB) && (!IS_EMPTY(LB))) { grid[y][x+1] = grid[y][x]; grid[y][x] = EMPTY; y--; x = width - 2; } } } } bool ADDNEWCOLUMNS() { bool anyNew = 0; for (int x = 0; x < width; x++) { if (IS_EMPTY(grid[height-1][x])) { anyNew = 1; int rand = RandomNumber(height + 1, 1); int rand2; for (int y = height - 1; y >= height - (rand - 1); y--) { rand2 = RandomNumber(4, 0); grid[y][x] = rand2; } } } return anyNew; } bool CHECKFORFINISH() { bool fin = 1; for (int y = 0; y < height; y++) { for (int x = 0; x < width; x++) { if (IS_EMPTY(grid[y][x])) continue; if (!IS_EMPTY(grid[y][x+1]) && x < width - 2) if (grid[y][x] == grid[y][x+1]) return 0; if (!IS_EMPTY(grid[y][x-1]) && x > 1) if (grid[y][x] == grid[y][x-1]) return 0; if (!IS_EMPTY(grid[y+1][x]) && y < height - 2) if (grid[y][x] == grid[y+1][x]) return 0; if (!IS_EMPTY(grid[y-1][x]) && y > 1) if (grid[y][x] == grid[y-1][x]) return 0; } } return 1; } void COUNTBALLS(HWND hwnd) { int ballcount[4]; // Red, Green, Blue, Yellow for (int i = 0; i < 4; i++) ballcount[i] = 0; for (int y = 0; y < height; y++) { for (int x = 0; x < width; x++) { switch (grid[y][x]) { case RED: ballcount[0]++; break; case GREEN: ballcount[1]++; break; case BLUE: ballcount[2]++; break; case YELLOW: ballcount[3]++; break; } } } string txt; txt = "Reds:\t\t"; txt += INTTOCHARP(ballcount[0]); txt += "\nGreens:\t\t"; txt += INTTOCHARP(ballcount[1]); txt += "\nBlues:\t\t"; txt += INTTOCHARP(ballcount[2]); txt += "\nYellows:\t\t"; txt += INTTOCHARP(ballcount[3]); MessageBox(hwnd, (char *) txt.c_str(), "Ball count", MB_OK); } HBITMAP GETBALLBMP(UINT ball) { switch (ball) { case IDB_BLUE1: return BLUEBMP; break; case IDB_GREEN1: return GREENBMP; break; case IDB_RED1: return REDBMP; break; case IDB_YELLOW1: return YELLOWBMP; break; case IDB_BLUE2: return BLUEBMP_S; break; case IDB_GREEN2: return GREENBMP_S; break; case IDB_RED2: return REDBMP_S; break; case IDB_YELLOW2: return YELLOWBMP_S; break; } return NULL; } UINT GETBALLINDEX(int ball, bool selected) { // Retrieves Ball ID bi = ball ^ (selected ? SELECTED : 0); switch (bi) { case BLUE: return IDB_BLUE1; break; case GREEN: return IDB_GREEN1; break; case RED: return IDB_RED1; break; case YELLOW: return IDB_YELLOW1; break; case BLUE | SELECTED: return IDB_BLUE2; break; case GREEN | SELECTED: return IDB_GREEN2; break; case RED | SELECTED: return IDB_RED2; break; case YELLOW | SELECTED: return IDB_YELLOW2; break; } return EMPTY; } void CLIENTRESIZE(HWND hWnd, int nWidth, int nHeight) { RECT rcClient, rcWindow; POINT ptDiff; GetClientRect(hWnd, &rcClient); GetWindowRect(hWnd, &rcWindow); ptDiff.x = (rcWindow.right - rcWindow.left) - rcClient.right; ptDiff.y = (rcWindow.bottom - rcWindow.top) - rcClient.bottom; MoveWindow(hWnd,rcWindow.left, rcWindow.top, nWidth + ptDiff.x, nHeight + ptDiff.y, TRUE); } void DRAWSTATUS(HDC hdc) { _itoa_s(score, _score, 10, 10); TextOut(hdc, 10, 3 + ballSize * height, "Score:", 6); TextOut(hdc, 70, 3 + ballSize * height, _score, GETINTLENGTH(score)); if (width < 11) return; _itoa_s(tempScore, _tempscore, 10, 10); TextOut(hdc, 150, 3 + ballSize * height, "Selection value:", 16); TextOut(hdc, 270, 3 + ballSize * height, _tempscore, GETINTLENGTH(tempScore)); } void StartDelay(HWND hwnd, int dur, int id) { idg = 1; SetTimer(hwnd, id, dur, NULL); } void EndDelay(HWND hwnd, int id) { KillTimer(hwnd, id); } void FuncAfterDelay(HWND hwnd, void (*f)(HWND), int dur, int id) { delayFunction = f; StartDelay(hwnd, dur, id); } // int CALLBACK Dimensions(HWND hDlg, UINT message, WPARAM wParam, LPARAM lParam) { UNREFERENCED_PARAMETER(lParam); switch (message) { case WM_INITDIALOG: { SetDlgItemText(hDlg, IDC_WIDTH, INTTOCHARP(width)); SetDlgItemText(hDlg, IDC_HEIGHT, INTTOCHARP(height)); return (INT_PTR)TRUE; } case WM_COMMAND: { switch (LOWORD(wParam)) { case IDOK: { _w = GetDlgItemInt(hDlg, IDC_WIDTH, 0, 0); _h = GetDlgItemInt(hDlg, IDC_HEIGHT, 0, 0); _w = _w > 40 ? 40 : _w < 5 ? 5 : _w; _h = _h > 30 ? 30 : _h < 5 ? 5 : _h; EndDialog(hDlg, LOWORD(wParam)); return IDOK; } break; case IDCANCEL: { EndDialog(hDlg, LOWORD(wParam)); return IDCANCEL; } break; } } break; } return (INT_PTR)FALSE; } void SHIFTR(HWND hwnd) { SHIFTALLRIGHT(); REPAINT(hwnd); EndDelay(hwnd, ID_DELAY2); if (CHECKFORFINISH()) { MessageBox(hwnd, "Finished!", "End", MB_OK); if (MessageBox(hwnd, "Do you want to start a new game?", (char*) L"", MB_YESNO | MB_ICONWARNING) == IDYES) { CLIENTRESIZE(hwnd, width * ballSize, 23 + (height * ballSize)); NEWGAME(hwnd); } } idg = 0; } void SHIFT(HWND hwnd) { SHIFTALLDOWN(); if (MEGASHIFT) { while (ADDNEWCOLUMNS()); REPAINT(hwnd); FuncAfterDelay(hwnd, SHIFTR, 100, ID_DELAY2); } REPAINT(hwnd); score += tempScore; tempScore = 0; if (!MEGASHIFT) idg = 0; EndDelay(hwnd, ID_DELAY); } LRESULT CALLBACK WndProc(HWND hwnd, UINT msg, WPARAM wParam, LPARAM lParam) { switch (msg) { case WM_TIMER: { delayFunction(hwnd); } break; case WM_COMMAND: { switch (LOWORD(wParam)) { case ID_OPTIONS_DIMENSIONS: { int ret = (int) DialogBox(NULL, MAKEINTRESOURCE(IDD_DIMENSIONS), hwnd, Dimensions); if (ret == IDOK) { if (MessageBox(hwnd, "Do you want to start a new game?", "Warning", MB_YESNO | MB_ICONWARNING) == IDYES) { CLIENTRESIZE(hwnd, _w * ballSize, 23 + (_h * ballSize)); width = _w; height = _h; NEWGAME(hwnd); } } } break; case ID_OPTIONS_MEGASHIFT: { if (MessageBox(hwnd, "Do you want to start a new game?", "Warning", MB_YESNO | MB_ICONWARNING) == IDYES) { NEWGAME(hwnd); if (!MEGASHIFT) { SetWindowText(hwnd, "SameGame - Megashift"); MEGASHIFT = 1; } else { SetWindowText(hwnd, "SameGame"); MEGASHIFT = 0; } } } break; case ID_GAME_NEWGAME: { NEWGAME(hwnd); } break; case ID_GAME_EXIT: { DestroyWindow(hwnd); } break; case ID_HELP_ABOUT: { MessageBox(hwnd, "William Hemsworth\n2008 March 7", "About", MB_OK | MB_ICONINFORMATION); } break; case ID_HELP_RULES: { MessageBox(hwnd, " Same Game\n\n\ The aim of the game is to try and get the\n\ highest score possible and to do that you\n\ need to try and gather as many same coloured balls\n\ together to retrieve the highest amounts of\n\ points once clicked.", "Rules", MB_OK); } break; case ID_TOOLS_COUNTCOLOURS: { COUNTBALLS(hwnd); } break; } } break; case WM_KEYDOWN: { switch (LOWORD(wParam)) { case 112: { try { COUNTBALLS(hwnd); } catch (void *v) { } } break; case 113: NEWGAME(hwnd); break; case 27: DestroyWindow(hwnd); break; } } break; case WM_LBUTTONDOWN: { if (idg) break; // If in a delay bc = 0; POINT pt; GetCursorPos(&pt); ScreenToClient(hwnd, &pt); int x = pt.x / ballSize; int y = pt.y / ballSize; if (IS_EMPTY(grid[y][x])) { tempScore = 0; UNSELECTALL(); REPAINT(hwnd); break; } bool alreadySelected = IS_SELECTED((int)grid[y][x]); if (!alreadySelected) { UNSELECTALL(); FLOOD(x,y,(int)grid[y][x]); tempScore = ((bc*bc)+(3*bc)+4); if (bc==1) { UNSELECTALL(); tempScore = 0; REPAINT(hwnd); break; } REPAINT(hwnd); } else { REMOVEALLSELECTED(); PlaySound((char*)IDR_POP,NULL,SND_RESOURCE|SND_ASYNC); REPAINT(hwnd); FuncAfterDelay(hwnd, SHIFT, 100, ID_DELAY); } } break; case WM_CLOSE: { DeleteObject(BLUEBMP); DeleteObject(GREENBMP); DeleteObject(REDBMP); DeleteObject(YELLOWBMP); DeleteObject(BLUEBMP_S); DeleteObject(GREENBMP_S); DeleteObject(REDBMP_S); DeleteObject(YELLOWBMP_S); DeleteObject(pen); DeleteObject(panel); DeleteObject(hdc); DeleteObject(bmp); DeleteObject(_hdc); DeleteObject(_hdcMem); DeleteObject(hbmOld); DestroyWindow(hwnd); } break; case WM_ERASEBKGND: { hdc = GetDC(hwnd); SelectObject(hdc , pen); for (unsigned int y = 0; y < (unsigned int) height; y++) { for (unsigned int x = 0; x < (unsigned int) width; x++) { if (!IS_EMPTY(grid[y][x])) continue; Rectangle(hdc, x * ballSize, y * ballSize, (x * ballSize) + ballSize, (y * ballSize) + ballSize); } } SelectObject(hdc , panel); Rectangle(hdc, 0, height * ballSize, width * ballSize, 23 + (height * ballSize)); MoveToEx(hdc, 0, height * ballSize, NULL); LineTo(hdc, ballSize * width, ballSize * height); DRAWSTATUS(hdc); } break; case WM_PAINT: { _hdc = BeginPaint(hwnd, &ps); _hdcMem = CreateCompatibleDC(_hdc); for (unsigned int y = 0; y < (unsigned int) height; y++) { for (unsigned int x = 0; x < (unsigned int) width; x++) { if (IS_EMPTY(grid[y][x])) continue; bmp = GETBALLBMP(GETBALLINDEX(grid[y][x], 0)); hbmOld = (HBITMAP) SelectObject(_hdcMem, bmp); GetObject(bmp, sizeof(bm), &bm); BitBlt(_hdc, x * ballSize, y * ballSize, bm.bmWidth, bm.bmHeight, _hdcMem,0, 0, SRCCOPY); } } SelectObject(_hdcMem, hbmOld); DeleteDC(_hdcMem); EndPaint(hwnd, &ps); } break; case WM_CREATE: { CLIENTRESIZE(hwnd, width * ballSize, 23 + (height * ballSize)); NEWGAME(hwnd); } break; case WM_DESTROY: { PostQuitMessage(0); } break; default: return DefWindowProc(hwnd, msg, wParam, lParam); } return 0; } int WINAPI WinMain(HINSTANCE hInstance, HINSTANCE hPrev, char *cmdl, int nShowCmd) { WNDCLASSEX wc; HWND hwnd; MSG msg; wc.cbClsExtra = 0; wc.cbSize = sizeof(WNDCLASSEX); wc.cbWndExtra = 0; wc.hCursor = LoadCursor(NULL, IDC_ARROW); wc.hbrBackground = (HBRUSH) CreateSolidBrush(RGB(255,255,255)); wc.hInstance = hInstance; wc.hIcon = LoadIcon(wc.hInstance, MAKEINTRESOURCE(IDI_ICON2)); wc.hIconSm = LoadIcon(wc.hInstance, MAKEINTRESOURCE(IDI_ICON2)); wc.lpfnWndProc = WndProc; wc.lpszClassName = cn; wc.lpszMenuName = MAKEINTRESOURCE(IDR_MENU1); wc.style = 0; if (!RegisterClassEx(&wc)) { MessageBox(NULL, (char*)L"Error, coulden't register window class", (char*)L"Error", MB_OK); return 1; } hwnd = CreateWindowEx(WS_EX_APPWINDOW, cn, "SameGame", WS_OVERLAPPED | WS_CAPTION | WS_SYSMENU | WS_MINIMIZEBOX, 300, 200, width * ballSize, height * ballSize, NULL, NULL, hInstance, NULL); if (hwnd == NULL) { MessageBox(NULL, (char*)L"Error, coulden't create the window", (char*)L"Error", MB_OK); return 1; } ShowWindow(hwnd, nShowCmd); UpdateWindow(hwnd); while (GetMessage(&msg, NULL, 0, 0) > 0) { TranslateMessage(&msg); DispatchMessage(&msg); } return (int) msg.wParam; }
http://www.2shared.com/file/3022171/.../SameGame.html
variables _score and _tempscore -- why use new to allocate only a single character? That seems like such as misuse of dynamic memory allocation. And those two variables appear to be used without ever initializing them to anything. Is there code that you didn't post that actually sets them to something ?
Last edited by Ancient Dragon; Mar 21st, 2008 at 7:15 pm.
Don't PM me with questions -- you might get a nasty PM in response. If you have a question then post it in one of the forums.
•
•
Join Date: Nov 2007
Posts: 978
Reputation:
Solved Threads: 208
Because of the way how you use _itoa_s(...) and the related buffers, _score, _tempscore and val, the program runs currently on good luck.
You could change all the _itoa_s() calls to use a single array of chars of sufficient size,
i.e.
You could change all the _itoa_s() calls to use a single array of chars of sufficient size,
i.e.
C++ Syntax (Toggle Plain Text)
static char itoa_conv_buff[MAX_BUF_LEN_HERE]; _itoa_s(num, itoa_conv_buff, MAX_BUF_LEN_HERE, 10);
•
•
Join Date: Nov 2007
Posts: 978
Reputation:
Solved Threads: 208
The _itoa_s() did not actually have much to do with the memory leaking, it was just a safety measure so that your program will not crash.
About the memory leaks, I think there's at least two places where it happens
1) For each SetTimer() call there should to be counterpart KillTimer() to use the timer resources properly.
2) You are not calling ReleaseDC(hwnd, hdc) in your WM_ERASEBKGND handler, i.e. every hdc you get using GetDC() is to be released by ReleaseDC(hwnd, hdc).
About the memory leaks, I think there's at least two places where it happens
1) For each SetTimer() call there should to be counterpart KillTimer() to use the timer resources properly.
2) You are not calling ReleaseDC(hwnd, hdc) in your WM_ERASEBKGND handler, i.e. every hdc you get using GetDC() is to be released by ReleaseDC(hwnd, hdc).
![]() |
Similar Threads
- memory management in wndows 2000 (Windows NT / 2000 / XP)
- school project: simple C++ game (need help with keyboard input) (C++)
- Memory leak? And other issues. (Windows Software)
- Completely Out of ideas Please help (Troubleshooting Dead Machines)
Other Threads in the C++ Forum
- Previous Thread: Change element in vector
- Next Thread: Trying to get started in port programming
| Thread Tools | Search this Thread |
api application array arrays based beginner binary c++ c/c++ calculator char char* class classes code compile compiler console conversion count delete deploy desktop directshow dll download dynamic dynamiccharacterarray encryption error file forms fstream function functions game givemetehcodez google graph gui homeworkhelp iamthwee ifstream input int java lib library linkedlist linker list loop looping loops map math matrix memory newbie news number numbertoword output pointer problem program programming project python random read recursion recursive reference return rpg simple sorting string strings studio temperature template templates test text text-file tree unix url variable vector video visual visualstudio win32 windows winsock wordfrequency wxwidgets






