Thread: Memory Leak Help

  1. #1
    Registered User (TNT)'s Avatar
    Join Date
    Aug 2001
    Location
    UK
    Posts
    339

    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
    Last edited by (TNT); 06-19-2006 at 04:11 AM.
    TNT
    You Can Stop Me, But You Cant Stop Us All

  2. #2
    and the hat of int overfl Salem's Avatar
    Join Date
    Aug 2001
    Location
    The edge of the known universe
    Posts
    39,660
    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.
    If you dance barefoot on the broken glass of undefined behaviour, you've got to expect the occasional cut.
    If at first you don't succeed, try writing your phone number on the exam paper.

  3. #3
    Registered User mikahell's Avatar
    Join Date
    Jun 2006
    Posts
    114
    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

  4. #4
    Codebot
    Join Date
    Jun 2004
    Location
    Toronto
    Posts
    195

    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.
    Last edited by Mastadex; 06-19-2006 at 11:27 AM.
    Founder and avid member of the Internationsl Typo Associateion

Popular pages Recent additions subscribe to a feed

Similar Threads

  1. Memory leak in this case?
    By George2 in forum C++ Programming
    Replies: 3
    Last Post: 03-22-2008, 05:05 AM
  2. memory leak in the code?
    By George2 in forum C++ Programming
    Replies: 20
    Last Post: 01-13-2008, 06:50 AM
  3. Is this code memory leak free? ---> POSIX Threads
    By avalanche333 in forum C++ Programming
    Replies: 9
    Last Post: 04-13-2007, 03:19 PM
  4. Any Memory Leak Checking Tool?
    By George2 in forum C Programming
    Replies: 4
    Last Post: 06-21-2006, 11:02 PM
  5. Manipulating the Windows Clipboard
    By Johno in forum Windows Programming
    Replies: 2
    Last Post: 10-01-2002, 09:37 AM