Memory Leakage

 Delphi About oops Error Handle DLL DllForms Sql Commands XML XML  Extension API MessageBox  API DELPHI Memory Leakage I|O ERROR Guest Book Malai

MemCheck tutorial: find memory leaks

Hunting memory leaks is the main use and the initial motivation for MemCheck: in 1994, our project was on a reasonable size (about 1000 classes in 150 000 lines of code); yet we discovered that it consumed more and more memory as it was being used, due to memory leaks (this was on Turbo Pascal).
Thinking about it, we decided that it was not difficult and could be funny to write our own memory manager which would log each memory allocation and deallocation, to find out how much was lost. That was the basic idea. The very first version just reported something like "hey, there were 56 allocations which have not been freed, leading to 996 bytes lost" (ok, I won't say here how much it really reported the first time we ran it on OptIt - just that today we know for sure there are no memory leaks in the parts of the code we actually use).
Ok, let's go for a short demo of what MemCheck can do now...

  1. Launch Delphi
  2. In tools/Debugger options, ensure "stop on Delphi exceptions" is checked
  3. File/New application
  4. Close Unit1 without saving (this will be a formless app)
  5. Add the memcheck unit to the project
  6. In the project dpr file, just above the begin end, insert:
        procedure Leak;
            begin
                TObject.Create;
            end;
  7. In the project's dpr file, make the body (begin...end part) contain
        begin
            MemChk;
            Leak;
        end.
  8. Go to Project/Options/Compiler. Set everything for debugging (no optimization, stack frames, all debugging)
  9. Go to Project/Options/Linker. Include TD32 debug info.
  10. Build all
  11. If you run in the debugger, the program will execute and on termination, Delphi will show you where the leak is by raising an exception on the buggy line (this is the user interface of MemCheck: we just use Delphi itself !). The text file is less useful in this case.
  12. If you run outside the debugger, you'll use the text file to understand the leak (see below - in fact, today even with the debugger I prefer to use the text file).
  13. OK, let's improve a little... Add another procedure
       procedure CallLeak;
            begin
                Leak;
            end;
  14. In the project's dpr file, make the body (begin...end part) contain
       var
    i: integer;
       begin
            MemChk;
    for i:= 1 to 5 do
                CallLeak;
        end.

Reading the text file

In the example above, the text file tells you...

  • There are a total of twenty bytes lost in memory leaks
  • Five instances of TObject are lost; their size is four bytes; they were allocated in routine Leak, and the line number is given
  • The routine Leak was called by CallLeak
  • The routine CallLeak was called by the initialization
  • MemCheck can not give any symbolic information for the next step in the call stack because Delphi did not generate any debugging information for these. In Fact, these two addresses are not in your program's code segment.
  • The order in which the leaks occured is given

InsGet the call stack information in the debugger

Again, this was written before the debug info was available in the text file. So today this is less useful.

  1. Run the example above
  2. The debugger tells you there is a leak in the routine Leak
  3. Press Ctr-F7 and evaluate the global boolean variable ShowCallStack (it is defined in MemCheck). Change it to True.
  4. Press F9. The debugger shows you the calling line. You can go on seeing the stack...