-
Memory Leak Help
Hi,
Im having some problems with a memory leak in some of my code, to be honest i have never really covered much 'memory managment' in the past and i have been away from programming for a few years, In the code below, the top function is called every so often, and upps the programs memory quite significantly over the course of a few minutes/several calls.
I allocated the main buffer memory with GlobalAlloc and free it later on with GlobalFree(). I cant think whats causing the leak? In the second function i assume strstr allocates memory itself?
Any ideas?
Code:
bool CheckData(HWND hWnd, wchar_t szUserName[128], wchar_t szPasswd[128], wchar_t szTmpPath[], data *md)
{
HINTERNET hInternet;
HINTERNET hConnect;
LPCTSTR szServer;
LPCWSTR szRSSLocation;
HINTERNET hRequest;
BOOL bResult;
HANDLE hFile;
DWORD dwBytesAvailable;
md->error = 0; // No Errors Yet!
wchar_t file_path[max_path];
wchar_t szDataFile[9] = _T("rss.xml");
szServer = _T("");
szRSSLocation = _T("");
wcscpy_s(file_path, lengthof(file_path), szTmpPath);
wcscat_s(file_path, lengthof(file_path), szDataFile);
hInternet = InternetOpen(_T("WinInetGet/0.1"), INTERNET_OPEN_TYPE_PRECONFIG, NULL, NULL, 0);
if(hInternet == NULL)
{
md->error = INTERNET_HAN;
return false;
}
hConnect = InternetConnect(hInternet, szServer, INTERNET_DEFAULT_HTTPS_PORT, szUserName,
szPasswd, INTERNET_SERVICE_HTTP, 0, 0);
if(hConnect == NULL)
{
md->error = INTERNET_HAN;
return false;
}
hRequest = HttpOpenRequest(hConnect, _T("GET"), szRSSLocation, NULL,
NULL, NULL,
INTERNET_FLAG_SECURE, 0);
if(hRequest == NULL)
{
md->error = INTERNET_HAN;
return false;
}
bResult = HttpSendRequest(hRequest, NULL, 0, NULL, 0);
if(bResult == FALSE)
{
md->error = ERR_HTTP_REQ;
return false;
}
hFile = CreateFile(file_path, GENERIC_WRITE, 0, NULL, OPEN_ALWAYS, FILE_ATTRIBUTE_NORMAL, NULL);
if(hFile == INVALID_HANDLE_VALUE)
{
md->error = ERR_FILE_HANDLE;
return false;
}
while (InternetQueryDataAvailable(hRequest, &dwBytesAvailable, 0, 0))
{
BYTE *pMessageBody = (BYTE *) GlobalAlloc(GMEM_FIXED, dwBytesAvailable+1);
DWORD dwBytesRead;
DWORD dwWritten;
BOOL bResult = InternetReadFile(hRequest, pMessageBody,
dwBytesAvailable, &dwBytesRead);
if (!bResult)
{
md->error = ERR_HTTPS_FAIL;
GlobalFree(pMessageBody);
return false;
break;
}
if (dwBytesRead == 0)
break; // EOF
pMessageBody[dwBytesRead] = '\0';
if(hFile != INVALID_HANDLE_VALUE)
{
WriteFile(hFile, pMessageBody, dwBytesRead, &dwWritten, NULL);
}
else
{
md->error = ERR_FILE_HANDLE;
GlobalFree(pMessageBody);
break;
}
// Free Memory
GlobalFree(pMessageBody);
}
// Close connections
CloseHandle(hFile);
InternetCloseHandle(hInternet);
InternetCloseHandle(hConnect);
InternetCloseHandle(hRequest);
// Begin XML Parsing
bResult = ParseXML(file_path, md);
if(bResult == FALSE)
{
md->error = ERR_PARSE;
}
// Delete temp XML file
DeleteFile(file_path);
if(md->error == 0)
return true;
else
return false;
}
bool ParseXML(LPCWSTR XMLFile, data *md)
{
HANDLE hFile;
DWORD dwActBytes;
DWORD filesize;
char *szXML;
char *nodea;
char nodeb[13];
hFile = CreateFile(XMLFile, GENERIC_READ, FILE_SHARE_READ, NULL, OPEN_ALWAYS, FILE_ATTRIBUTE_NORMAL, NULL);
if(hFile != INVALID_HANDLE_VALUE)
{
// Get file size and allocate buffer memory
filesize = GetFileSize(hFile, NULL);
szXML = (char *) GlobalAlloc(GMEM_FIXED, filesize+1);
SetFilePointer(hFile, 0, NULL, FILE_BEGIN);
// read in entire xml file into the XML buffer
ReadFile(hFile, szXML, filesize, &dwActBytes, NULL);
szXML[dwActBytes] = 0;
CloseHandle(hFile);
MessageBoxA(NULL, szXML, "XML Data", NULL);
}
else
{
return false;
}
// Get the <data> node
nodea = strstr(szXML, "<data>");
if(nodea != NULL)
{
nodeb[0] = nodea[11];
int pos = 0;
int a = 11;
do
{
nodeb[pos] = nodea[a];
pos++;
a++;
} while(nodea[a] != '<');
nodeb[pos] = 0;
// Fill in the data structure
md->new_messages = atoi(nodeb);
}
else
{
md->error = ERR_UNAUTH;
}
// Free Memory
GlobalFree(szXML);
return true;
}
Thanks very much for any help/advice on correct memory allocation :rolleyes:
-
if (dwBytesRead == 0)
break; // EOF
This one does NOT call globalFree()
Why are you bothering with alloc/free anyway?
InternetReadFile could be used with a fixed-length buffer, and that makes the whole memory management problem go away.
-
I'm not familiar with this kind of internet coding, but by reading it I think that the problem lies in "CheckData", because it seems to me that you have more "GlobalAlloc" than "GlobalFree"... but that's speaking of the dynamic memory, because I know that even when a function ends, the dynamic allocated memory doens't free itself automaticaly, or at least you can always pass twice (or more) on the same line of code, which is used to allocate dynamic memory... so you end up with the same variable at two or more place in memory, but can just access to the last one you created... Take a look at this:
Code:
double *a;
while (1) {
a = new double;
}
ok I'm not sure if that was exactly it, but I remember once I did something like this, (without "while(1)" :) ) and each time the app was reading the line with "new", it just allocated a new memory block, without deallocating the previous one...for the same variable. So this can maybe be what's going on in your code, but as I told you, I don't really know about the functions you used in your code, so it maybe another thing...
Good luck
-
Quick Tip on debugging.
If your using visual studio 7 (and higher), ther are a few debugging tools that can help you find a leak.
firstly put this at the begining of your program:
Note that this does not account for variables that are NOT dynamically allocated. so if your have something like int i; put this line after it. This is done because if you int i; is create inside the debugger checking code, then it will not be destroyed until the program/function ends. That will report a false leak.
Code:
#ifdef _DEBUG
_CrtSetDbgFlag(_CRTDBG_LEAK_CHECK_DF | _CRTDBG_ALLOC_MEM_DF | _CRTDBG_CHECK_ALWAYS_DF);
#endif
Then to stop the debugging just put this in your code at the end of your program:
Code:
#ifdef _DEBUG
if (_CrtDumpMemoryLeaks())
{
MessageBox(SomeHWND, "MEMORY LEAK DETECTED: ", "THIS IS BAD!", MB_OK);
}
#endif
Make sure to include the correct header file so that this works:
Code:
#include <crtdbg.h>
What you will get is a message box appearing whenever you actually have a memsory leak. Here is an example of how I have written code using it.
Code:
int WINAPI WinMain(HINSTANCE hInstance, HINSTANCE hPrevInstance, LPSTR lpCmdLine, int nCmdShow)
{
int i; // THIS SHOULD BE INSTANCIATED BEFORE THE DEBUGGER CHECK
#ifdef _DEBUG
_CrtSetDbgFlag(_CRTDBG_LEAK_CHECK_DF | _CRTDBG_ALLOC_MEM_DF | _CRTDBG_CHECK_ALWAYS_DF);
#endif
int *k = new int; // THIS IS A MEMORY LEAK!!!!!!!
int *j = new int; // this is not a memory leak
delete j;
#ifdef _DEBUG
if (_CrtDumpMemoryLeaks())
{
MessageBox(SomeHWND, "MEMORY LEAK DETECTED: ", "THIS IS BAD!", MB_OK);
}
#endif
return 0;
} // THIS IS WHERE int i GETS DESTROYED
if you run this code, it will report a leak inside the OUTPUT window in visual studio. And it might look something like this:
Code:
Detected memory leaks!
Dumping objects ->
{54} normal block at 0x00853FA8, 4 bytes long.
Data: < > CD CD CD CD
Object dump complete.
Detected memory leaks!
Dumping objects ->
{54} normal block at 0x00853FA8, 4 bytes long.
Data: < > CD CD CD CD
Object dump complete.
The program '[3144] test.exe: Native' has exited with code 0 (0x0).
Since an int is 4 bytes on a 32bit machine, it tells me what when wrong. Although im still experimenting with this, so it cant tell you exactly where its leaking, but it provides clues.