This is an old revision of the document!
Using Memory Profiler
Project Setup
- Project > Options > Compiler
- Code Generation:
- Optimization
- Stack Frames
- Debugging:
- Debug Information
- Project > Options > Linker
- Include TD32 debug info
- Map File: Detailed
- Build project (Project > Build All Projects).
AQTime
- Run AQTime and include project executable to debug (File > Open > choose the .exe file).
- Select profiler to execute: Options > Profile Options (or from drop-down in toolbar). Use VCL > VCL Class Profiler.
- Run executable with profiler (Project > Run).
- Test and push the executable to try to break it. Once you are done with tests, simply quit the application.
- Review memory leaks report in AQTime (it takes a few seconds to update after the tested application has exited).
Using Built-in Debugging Tools
Using FastMM
- Download FastMM (Fast Memory Manager), and FastMM Options Interface GUI
- Open project in Delphi.
- Install FastMM in your project and source code (see instructions distributed with FastMM package).
- Set
FullDebugMode
in Project > Options > Directories/Conditionals > Conditional defines. - Build project (Project > Build All Projects).
- Execute project as usual. A dialog will popup if there are any critical errors or memory leaks during run time.
Example, in MyProject.dpr
:
program MyProject; {$DEFINE FullDebugMode} // for software that needs debug reporting using FastMM4 uses FastMM4 {memory manager replacement (and mem leak detector)}, Forms, Windows, sysUtils, messages, Dialogs, Classes; begin OutputDebugString(pchar('DBGVIEWCLEAR')); // clear DebugView window (get from www.sysinternals.com) // register with FastMM4 some known memory leaks RegisterExpectedMemoryLeak(28 {21-28}, 1); // TCriticalSection x 1 RegisterExpectedMemoryLeak(44 {37-44}, 1); // TShellFolder x 1 RegisterExpectedMemoryLeak(60 {45-60}, 1); // TStringList x 1 FastMM4.ReportMemoryLeaksOnShutdown := DebugHook <> 0; // report leaks only when using debugger . . . project code here . . . end.
In FastMM4Options.inc
, enable the following define statements:
{$define UseOutputDebugString} {$define LogErrorsToFile} {$define LogMemoryLeakDetailToFile} {$define ClearLogFileOnStartup} {$define EnableMemoryLeakReporting} {$define HideExpectedLeaksRegisteredByPointer} {$define RequireDebuggerPresenceForLeakReporting} {$define RequireDebugInfoForLeakReporting}
References
- New Memory Manage in BDS 2006: http://dn.codegear.com/articles/33416
Using EventLog or DebugView
Create some debugging routines in DebugTools.pas
(Pascal unit):
//------------------------------------------------------------------------------ // Unit Name: DebugTools // Author: Siegwart Mayr // Date: 17-May-2006 // Purpose: Library with debugging routines. //------------------------------------------------------------------------------ unit DebugTools; interface Uses Windows, Forms; //------------------------------------------- // types //------------------------------------------- Type TOutlineNodeType = (ntEmpty, ntNode, ntLeaf); //------------------------------------------- // function prototypes //------------------------------------------- procedure DebugMsg(str: string; OutlineLevel: integer=0; NodeType: TOutlineNodeType=ntNode); procedure DebugStr(str: string); //------------------------------------------- // resource strings //------------------------------------------- ResourceString rsOutlineBullet = '+'; rsOutlineLeaf = '-'; rsOutlineEmpty = '|'; implementation //------------------------------------------------------------------------------ // description: Send the specified string to the Windows debugger environment, // so that it can be viewed with DbgViewer (http://www.sysinternals.com) // parameters : str: string, OutlineLevel: integer, NoteType: TOutlineNodeType // return : None //------------------------------------------------------------------------------ procedure DebugMsg(str: string; OutlineLevel: integer=0; NodeType: TOutlineNodeType=ntNode); {$ifdef FullDebugMode} var LevelSpacer: string; NodeSymbol: string; {$endif} begin {$ifdef FullDebugMode} case NodeType of ntEmpty: NodeSymbol := rsOutlineEmpty; ntNode: NodeSymbol := rsOutlineBullet + rsOutlineBullet; ntLeaf: NodeSymbol := rsOutlineBullet + rsOutlineLeaf; else NodeSymbol := rsOutlineBullet; end; case OutlineLevel of 1: begin LevelSpacer := StringOfChar(' ', 1) + NodeSymbol; end; 2: begin LevelSpacer := StringOfChar(' ', 2) + NodeSymbol; end; 3: begin LevelSpacer := StringOfChar(' ', 3) + NodeSymbol; end; else LevelSpacer := ''; end; OutputDebugString(pchar(LevelSpacer + ' ' + str)); {$endif} end; //------------------------------------------------------------------------------ // description: Simple debugging routine. // parameters : str: string // return : None //------------------------------------------------------------------------------ procedure DebugStr(str: string); begin //{$ifdef FullDebugMode} OutputDebugString(pchar(str)); //{$endif} end; end.
- Include
DebugTools
in theUses
clause in the Delphi source code. - Insert
DebugStr('My debug message here…')
statements in the source code whenever something needs debugging. - Use one of these utilities to view debug messages as application is being executed:
- When application is run from Delphi's IDE: use Delphi's built-in Event Log (View > Debug Windows > Event Log (Ctrl-Alt-V)).
- When application is run by itself: use
DbgView.exe
utility (from http://www.sysinternals.com). Leave utility running while application is run as well.