Mega Code Archive

 
Categories / Delphi / Hardware
 

How to find memory leaks

Title: How to find memory leaks Question: What can you do if you know there is a resource or memory leak in your program ? Answer: Memory leaks are the black holes of programming, they continuously swallow resources which will never be released again. They can be a nightmare for a programmer: they are hard to find, and exceptions or errors appear only after a long time and usually not at the place of the leak itself. Contrary to Microsoft Dot Net, Delphi and the VCL have no garbage collector. You have to care for the release of each object yourself. It is for example easy to overlook an object in a list which is not destroyed if the list is released. Possible error messages due to resource and memory leaks are for example "The window does not have scroll bars" (Microsoft Error Code 1447) and "Out of system resources". What can you do if you know there is a resource or memory leak ? 1. Control the memory usage with the task manager 2. Use tools like the freeware program "MemProof". Other resource tracking tools are listed at http://www.undu.com/Articles/980807c.html 3. Check your program for functions and objects which have direct influence on memory: GetMem, FreeMem, Constructors, Destructors (esp. of composed and list objects), MapViewOfFile, etc. 4. Control the memory usage with API functions GlobalMemoryStatus() and GetProcessMemoryInfo(). Use for example a debug symbol defined with {$DEFINE DEBUG}, and show a few lables which display the memory usage if this symbol is defined: {$IFDEF DEBUG} TotalMemoryLabel.Visible:=true; FreeMemoryLabel.Visible:=true; ProcessMemoryLabel.Visible:=true; MemoryLeakLabel.Visible:=true; {$ENDIF} procedure TForm.DebugProcessStatus(s : string); var pmc: PPROCESS_MEMORY_COUNTERS; cb: Integer; MemStat: tMemoryStatus; begin MemStat.dwLength:=SizeOf(MemStat); GlobalMemoryStatus(MemStat); // Get the total and available system memory TotalMemoryLabel.Caption := 'Total system memory: '+ FormatFloat('###,###',MemStat.dwTotalPhys/1024)+' KByte'; FreeMemoryLabel.Caption := 'Free physical memory: '+ FormatFloat('###,###',MemStat.dwAvailPhys/1024)+' KByte'; // Get the used memory for the current process cb := SizeOf(TProcessMemoryCounters); GetMem(pmc, cb); pmc^.cb := cb; if GetProcessMemoryInfo(GetCurrentProcess(), pmc, cb) then begin NewWorkingMemory:=Longint(pmc^.WorkingSetSize); ProcessMemoryLabel.Caption := 'Process-Memory: '+ FormatFloat('###,###',NewWorkingMemory/1024)+' KByte'; MemoryLeakLabel.Caption := 'Memory Loss: '+ FormatFloat('###,###',(NewWorkingMemory-OldWorkingMemory)/1024)+' KByte'; OldWorkingMemory:=NewWorkingMemory; end; FreeMem(pmc); DebugStatusLabel.caption:='Status: '+s; end;