[Initranslator-svncheckins] SF.net SVN: initranslator: [193] translator/trunk/src
Brought to you by:
peter3
|
From: <pe...@us...> - 2006-12-14 00:46:01
|
Revision: 193
http://svn.sourceforge.net/initranslator/?rev=193&view=rev
Author: peter3
Date: 2006-12-13 16:46:01 -0800 (Wed, 13 Dec 2006)
Log Message:
-----------
- FastMM4 units added
Added Paths:
-----------
translator/trunk/src/FastMM4.pas
translator/trunk/src/FastMM4Messages.pas
translator/trunk/src/FastMM4Options.inc
Added: translator/trunk/src/FastMM4.pas
===================================================================
--- translator/trunk/src/FastMM4.pas (rev 0)
+++ translator/trunk/src/FastMM4.pas 2006-12-14 00:46:01 UTC (rev 193)
@@ -0,0 +1,7904 @@
+(*
+
+Fast Memory Manager 4.74
+
+Description:
+ A fast replacement memory manager for Borland Delphi Win32 applications that
+ scales well under multi-threaded usage, is not prone to memory fragmentation,
+ and supports shared memory without the use of external .DLL files.
+
+Homepage:
+ http://fastmm.sourceforge.net
+
+Advantages:
+ - Fast
+ - Low overhead. FastMM is designed for an average of 5% and maximum of 10%
+ overhead per block.
+ - Supports up to 3GB of user mode address space under Windows 32-bit and 4GB
+ under Windows 64-bit. Add the "$SetPEFlags $20" option (in curly braces)
+ to your .dpr to enable this.
+ - Highly aligned memory blocks. Can be configured for either 8-byte or 16-byte
+ alignment.
+ - Good scaling under multi-threaded applications
+ - Intelligent reallocations. Avoids slow memory move operations through
+ not performing unneccesary downsizes and by having a minimum percentage
+ block size growth factor when an in-place block upsize is not possible.
+ - Resistant to address space fragmentation
+ - No external DLL required when sharing memory between the application and
+ external libraries (provided both use this memory manager)
+ - Optionally reports memory leaks on program shutdown. (This check can be set
+ to be performed only if Delphi is currently running on the machine, so end
+ users won't be bothered by the error message.)
+ - Supports Delphi 4 (or later), C++ Builder 5 (or later), Kylix 3.
+
+Usage:
+ Delphi:
+ Place this unit as the very first unit under the "uses" section in your
+ project's .dpr file. When sharing memory between an application and a DLL
+ (e.g. when passing a long string or dynamic array to a DLL function), both the
+ main application and the DLL must be compiled using this memory manager (with
+ the required conditional defines set). There are some conditional defines
+ (inside FastMM4Options.inc) that may be used to tweak the memory manager. To
+ enable support for a user mode address space greater than 2GB you will have to
+ use the EditBin* tool to set the LARGE_ADDRESS_AWARE flag in the EXE header.
+ This informs Windows x64 or Windows 32-bit (with the /3GB option set) that the
+ application supports an address space larger than 2GB (up to 4GB). In Delphi 7
+ and later you can also specify this flag through the compiler directive
+ {$SetPEFlags $20}
+ *The EditBin tool ships with the MS Visual C compiler.
+ C++ Builder 6:
+ Refer to the instructions inside FastMM4BCB.cpp.
+
+License:
+ This work is copyright Professional Software Development / Pierre le Riche. It
+ is released under a dual license, and you may choose to use it under either the
+ Mozilla Public License 1.1 (MPL 1.1, available from
+ http://www.mozilla.org/MPL/MPL-1.1.html) or the GNU Lesser General Public
+ License 2.1 (LGPL 2.1, available from
+ http://www.opensource.org/licenses/lgpl-license.php). If you find FastMM useful
+ or you would like to support further development, a donation would be much
+ appreciated. My banking details are:
+ Country: South Africa
+ Bank: ABSA Bank Ltd
+ Branch: Somerset West
+ Branch Code: 334-712
+ Account Name: PSD (Distribution)
+ Account No.: 4041827693
+ Swift Code: ABSAZAJJ
+ My PayPal account is:
+ bo...@ps...
+
+Contact Details:
+ My contact details are shown below if you would like to get in touch with me.
+ If you use this memory manager I would like to hear from you: please e-mail me
+ your comments - good and bad.
+ Snailmail:
+ PO Box 2514
+ Somerset West
+ 7129
+ South Africa
+ E-mail:
+ pl...@ps...
+
+Support:
+ If you have trouble using FastMM, you are welcome to drop me an e-mail at the
+ address above, or you may post your questions in the BASM newsgroup on the
+ Borland news server (which is where I hang out quite frequently).
+
+Disclaimer:
+ FastMM has been tested extensively with both single and multithreaded
+ applications on various hardware platforms, but unfortunately I am not in a
+ position to make any guarantees. Use it at your own risk.
+
+Acknowledgements (for version 4):
+ - Eric Grange for his RecyclerMM on which the earlier versions of FastMM were
+ based. RecyclerMM was what inspired me to try and write my own memory
+ manager back in early 2004.
+ - Dennis Christensen for his tireless efforts with the Fastcode project:
+ helping to develop, optimize and debug the growing Fastcode library.
+ - Pierre Y. for his suggestions regarding the extension of the memory leak
+ checking options.
+ - Anders Isaksson and Greg for finding and identifying the "DelphiIsRunning"
+ bug under Delphi 5.
+ - Francois Malan for finding the bug that caused compilation to fail when
+ both the "AssumeMultiThreaded" and "CheckHeapForCorruption" options were set.
+ - Craig Peterson for helping me identify the cache associativity issues that
+ could arise due to medium blocks always being an exact multiple of 256 bytes.
+ Also for various other bug reports and enhancement suggestions.
+ - Jarek Karciarz, Vladimir Ulchenko (Vavan) and Bob Gonder for their help in
+ implementing the BCB support.
+ - Ben Taylor for his suggestion to display the object class of all memory
+ leaks.
+ - Jean Marc Eber and Vincent Mahon (the Memcheck guys) for the call stack
+ trace code and also the method used to catch virtual method calls on freed
+ objects.
+ - Nahan Hyn for the suggestion to be able to enable or disable memory leak
+ reporting through a global variable (the "ManualLeakReportingControl"
+ option.)
+ - Leonel Togniolli for various suggestions with regard to enhancing the bug
+ tracking features of FastMM and other helpful advice.
+ - Joe Bain and Leonel Togniolli for the workaround to QC#10922 affecting
+ compilation under Delphi 2005.
+ - Robert Marquardt for the suggestion to make localisation of FastMM easier by
+ having all string constants together.
+ - Simon Kissel and Fikret Hasovic for their help in implementing Kylix support.
+ - Matthias Thoma, Petr Vones, Robert Rossmair and the rest of the JCL team for
+ their debug info library used in the debug info support DLL and also the
+ code used to check for a valid call site in the "raw" stack trace code.
+ - Andreas Hausladen for the suggestion to use an external DLL to enable the
+ reporting of debug information.
+ - Alexander Tabakov for various good suggestions regarding the debugging
+ facilities of FastMM.
+ - M. Skloff for some useful suggestions and bringing to my attention some
+ compiler warnings.
+ - Martin Aignesberger for the code to use madExcept instead of the JCL library
+ inside the debug info support DLL.
+ - Diederik and Dennis Passmore for the suggestion to be able to register
+ expected leaks.
+ - Dario Tiraboschi and Mark Gebauer for pointing out the problems that occur
+ when range checking and complete boolean evaluation is turned on.
+ - Hanspeter Widmer for his suggestion to have an option to display install and
+ uninstall debug messages and moving options to a separate file.
+ - Arthur Hoornweg for notifying me of the image base being incorrect for
+ borlndmm.dll.
+ - Theo Carr-Brion and Hanspeter Widmer for finding the false alarm error
+ message "Block Header Has Been Corrupted" bug in FullDebugMode.
+ - Danny Heijl for reporting the compiler error in "release" mode.
+ - Omar Zelaya for reporting the BCB support regression bug.
+ - Dan Miser for various good suggestions, e.g. not logging expected leaks to
+ file, enhancements the stack trace and messagebox functionality, etc.
+ - Arjen de Ruijter for fixing the bug in GetMemoryLeakType that caused it
+ to not properly detect expected leaks registered by class when in
+ "FullDebugMode".
+ - Aleksander Oven for reporting the installation problem when trying to use
+ FastMM in an application together with libraries that all use runtime
+ packages.
+ - Kristofer Skaug for reporting the bug that sometimes causes the leak report
+ to be shown, even when all the leaks have been registered as expected leaks.
+ Also for some useful enhancement suggestions.
+ - G\xFCnther Schoch for the "RequireDebuggerPresenceForLeakReporting" option.
+ - Jan Schl\xFCter for the "ForceMMX" option.
+ - Hallvard Vassbotn for various good enhancement suggestions.
+ - Mark Edington for some good suggestions and bug reports.
+ - Paul Ishenin for reporting the compilation error when the NoMessageBoxes
+ option is set and also the missing call stack entries issue when "raw" stack
+ traces are enabled, as well as for the Russian translation.
+ - Cristian Nicola for reporting the compilation bug when the
+ CatchUseOfFreedInterfaces option was enabled (4.40).
+ - Mathias Rauen (madshi) for improving the support for madExcept in the debug
+ info support DLL.
+ - Roddy Pratt for the BCB5 support code.
+ - Rene Mihula for the Czech translation.
+ - Artur Redzko for the Polish translation.
+ - Bart van der Werf for helping me solve the DLL unload order problem when
+ using the debug mode borlndmm.dll library.
+ - JRG ("The Delphi Guy") for the Spanish translation.
+ - Justus Janssen for Delphi 4 support.
+ - Vadim Lopushansky and Charles Vinal for reporting the Delphi 5 compile error
+ in version 4.50.
+ - Johni Jeferson Capeletto for the Brazilian Portuguese translation.
+ - Kurt Fitzner for reporting the BCb6 compiler error in 4.52.
+ - Michal Niklas for reporting the Kylix compiler error in 4.54.
+ - Thomas Speck and Uwe Queisser for German translations.
+ - Zaenal Mutaqin for the Indonesian translation.
+ - Carlos Macao for the Portuguese translation.
+ - Michael Winter for catching the performance issue when reallocating certain
+ block sizes.
+ - dzmitry[li] for the Belarussian translation.
+ - Marcelo Montenegro for the updated Spanish translation.
+ - Jud Cole for finding and reporting the bug which may trigger a read access
+ violation when upsizing certain small block sizes together with the
+ "UseCustomVariableSizeMoveRoutines" option.
+ - Zdenek Vasku for reporting and fixing the memory manager sharing bug
+ affecting Windows 95/98/Me.
+ - RB Winston for suggesting the improvement to GExperts "backup" support.
+ - Thomas Schulz for reporting the bug affecting large address space support
+ under FullDebugMode.
+ - Luigi Sandon for the Italian translation.
+ - Primoz Gabrijelcic for helping to track down the RawStackTraces A/V bug.
+ - Werner Bochtler and Markus Beth for suggesting the
+ "NeverSleepOnThreadContention" option.
+ - JiYuan Xie for the Simplified Chinese translation.
+ - Andrey Shtukaturov for the updated Russian translation, as well as the
+ Ukrainian translation.
+ - Dimitry Timokhov for finding two elusive bugs in the memory leak class
+ detection code.
+ - Paulo Moreno for fixing the AllocMem bug in FullDebugMode that prevented
+ large blocks from being cleared.
+ - Everyone who have made donations. Thanks!
+ - Any other Fastcoders or supporters that I have forgotten, and also everyone
+ that helped with the older versions.
+
+Change log:
+ Version 1.00 (28 June 2004):
+ - First version (called PSDMemoryManager). Based on RecyclerMM (free block
+ stack approach) by Eric Grange.
+ Version 2.00 (3 November 2004):
+ - Complete redesign and rewrite from scratch. Name changed to FastMM to
+ reflect this fact. Uses a linked-list approach. Is faster, has less memory
+ overhead, and will now catch most bad pointers on FreeMem calls.
+ Version 3.00 (1 March 2005):
+ - Another rewrite. Reduced the memory overhead by: (a) not having a separate
+ memory area for the linked list of free blocks (uses space inside free
+ blocks themselves) (b) batch managers are allocated as part of chunks (c)
+ block size lookup table size reduced. This should make FastMM more CPU
+ cache friendly.
+ Version 4.00 (7 June 2005):
+ - Yet another rewrite. FastMM4 is in fact three memory managers in one: Small
+ blocks (up to a few KB) are managed through the binning model in the same
+ way as previous versions, medium blocks (from a few KB up to approximately
+ 256K) are allocated in a linked-list fashion, and large blocks are grabbed
+ directly from the system through VirtualAlloc. This 3-layered design allows
+ very fast operation with the most frequently used block sizes (small
+ blocks), while also minimizing fragmentation and imparting significant
+ overhead savings with blocks larger than a few KB.
+ Version 4.01 (8 June 2005):
+ - Added the options "RequireDebugInfoForLeakReporting" and
+ "RequireIDEPresenceForLeakReporting" as suggested by Pierre Y.
+ - Fixed the "DelphiIsRunning" function not working under Delphi 5, and
+ consequently no leak checking. (Reported by Anders Isaksson and Greg.)
+ Version 4.02 (8 June 2005):
+ - Fixed the compilation error when both the "AssumeMultiThreaded" and
+ "CheckHeapForCorruption options were set. (Reported by Francois Malan.)
+ Version 4.03 (9 June 2005):
+ - Added descriptive error messages when FastMM4 cannot be installed because
+ another MM has already been installed or memory has already been allocated.
+ Version 4.04 (13 June 2005):
+ - Added a small fixed offset to the size of medium blocks (previously always
+ exact multiples of 256 bytes). This makes performance problems due to CPU
+ cache associativity limitations much less likely. (Reported by Craig
+ Peterson.)
+ Version 4.05 (17 June 2005):
+ - Added the Align16Bytes option. Disable this option to drop the 16 byte
+ alignment restriction and reduce alignment to 8 bytes for the smallest
+ block sizes. Disabling Align16Bytes should lower memory consumption at the
+ cost of complicating the use of aligned SSE move instructions. (Suggested
+ by Craig Peterson.)
+ - Added a support unit for C++ Builder 6 - Add FastMM4BCB.cpp and
+ FastMM4.pas to your BCB project to use FastMM instead of the RTL MM. Memory
+ leak checking is not supported because (unfortunately) once an MM is
+ installed under BCB you cannot uninstall it... at least not without
+ modifying the RTL code in exit.c or patching the RTL code runtime. (Thanks
+ to Jarek Karciarz, Vladimir Ulchenko and Bob Gonder.)
+ Version 4.06 (22 June 2005):
+ - Displays the class of all leaked objects on the memory leak report and also
+ tries to identify leaked long strings. Previously it only displayed the
+ sizes of all leaked blocks. (Suggested by Ben Taylor.)
+ - Added support for displaying the sizes of medium and large block memory
+ leaks. Previously it only displayed details for small block leaks.
+ Version 4.07 (22 June 2005):
+ - Fixed the detection of the class of leaked objects not working under
+ Windows 98/Me.
+ Version 4.08 (27 June 2005):
+ - Added a BorlndMM.dpr project to allow you to build a borlndmm.dll that uses
+ FastMM4 instead of the default memory manager. You may replace the old
+ DLL in the Delphi \Bin directory to make the IDE use this memory manager
+ instead.
+ Version 4.09 (30 June 2005):
+ - Included a patch fix for the bug affecting replacement borlndmm.dll files
+ with Delphi 2005 (QC#14007). Compile the patch, close Delphi, and run it
+ once to patch your vclide90.bpl. You will now be able to use the
+ replacement borlndmm.dll to speed up the Delphi 2005 IDE as well.
+ Version 4.10 (7 July 2005):
+ - Due to QC#14070 ("Delphi IDE attempts to free memory after the shutdown
+ code of borlndmm.dll has been called"), FastMM cannot be uninstalled
+ safely when used inside a replacement borlndmm.dll for the IDE. Added a
+ conditional define "NeverUninstall" for this purpose.
+ - Added the "FullDebugMode" option to pad all blocks with a header and footer
+ to help you catch memory overwrite bugs in your applications. All blocks
+ returned to freemem are also zeroed out to help catch bugs involving the
+ use of previously freed blocks. Also catches attempts at calling virtual
+ methods of freed objects provided the block in question has not been reused
+ since the object was freed. Displays stack traces on error to aid debugging.
+ - Added the "LogErrorsToFile" option to log all errors to a text file in the
+ same folder as the application.
+ - Added the "ManualLeakReportingControl" option (suggested by Nahan Hyn) to
+ enable control over whether the memory leak report should be done or not
+ via a global variable.
+ Version 4.11 (7 July 2005):
+ - Fixed a compilation error under Delphi 2005 due to QC#10922. (Thanks to Joe
+ Bain and Leonel Togniolli.)
+ - Fixed leaked object classes not displaying in the leak report in
+ "FullDebugMode".
+ Version 4.12 (8 July 2005):
+ - Moved all the string constants to one place to make it easier to do
+ translations into other languages. (Thanks to Robert Marquardt.)
+ - Added support for Kylix. Some functionality is currently missing: No
+ support for detecting the object class on leaks and also no MM sharing.
+ (Thanks to Simon Kissel and Fikret Hasovic).
+ Version 4.13 (11 July 2005):
+ - Added the FastMM_DebugInfo.dll support library to display debug info for
+ stack traces.
+ - Stack traces for the memory leak report is now logged to the log file in
+ "FullDebugMode".
+ Version 4.14 (14 July 2005):
+ - Fixed string leaks not being detected as such in "FullDebugMode". (Thanks
+ to Leonel Togniolli.)
+ - Fixed the compilation error in "FullDebugMode" when "LogErrorsToFile" is
+ not set. (Thanks to Leonel Togniolli.)
+ - Added a "Release" option to allow the grouping of various options and to
+ make it easier to make debug and release builds. (Thanks to Alexander
+ Tabakov.)
+ - Added a "HideMemoryLeakHintMessage" option to not display the hint below
+ the memory leak message. (Thanks to Alexander Tabakov.)
+ - Changed the fill character for "FullDebugMode" from zero to $80 to be able
+ to differentiate between invalid memory accesses using nil pointers to
+ invalid memory accesses using fields of freed objects. FastMM tries to
+ reserve the 64K block starting at $80800000 at startup to ensure that an
+ A/V will occur when this block is accessed. (Thanks to Alexander Tabakov.)
+ - Fixed some compiler warnings. (Thanks to M. Skloff)
+ - Fixed some display bugs in the memory leak report. (Thanks to Leonel
+ Togniolli.)
+ - Added a "LogMemoryLeakDetailToFile" option. Some applications leak a lot of
+ memory and can make the log file grow very large very quickly.
+ - Added the option to use madExcept instead of the JCL Debug library in the
+ debug info support DLL. (Thanks to Martin Aignesberger.)
+ - Added procedures "GetMemoryManagerState" and "GetMemoryMap" to retrieve
+ statistics about the current state of the memory manager and memory pool.
+ (A usage tracker form together with a demo is also available.)
+ Version 4.15 (14 July 2005):
+ - Fixed a false 4GB(!) memory leak reported in some instances.
+ Version 4.16 (15 July 2005):
+ - Added the "CatchUseOfFreedInterfaces" option to catch the use of interfaces
+ of freed objects. This option is not compatible with checking that a freed
+ block has not been modified, so enable this option only when hunting an
+ invalid interface reference. (Only relevant if "FullDebugMode" is set.)
+ - During shutdown FastMM now checks that all free blocks have not been
+ modified since being freed. (Only when "FullDebugMode" is set and
+ "CatchUseOfFreedInterfaces" is disabled.)
+ Version 4.17 (15 July 2005):
+ - Added the AddExpectedMemoryLeaks and RemoveExpectedMemoryLeaks procedures to
+ register/unregister expected leaks, thus preventing the leak report from
+ displaying if only expected leaks occurred. (Thanks to Diederik and Dennis
+ Passmore for the suggestion.) (Note: these functions were renamed in later
+ versions.)
+ - Fixed the "LogMemoryLeakDetailToFile" not logging memory leak detail to file
+ as it is supposed to. (Thanks to Leonel Togniolli.)
+ Version 4.18 (18 July 2005):
+ - Fixed some issues when range checking or complete boolean evaluation is
+ switched on. (Thanks to Dario Tiraboschi and Mark Gebauer.)
+ - Added the "OutputInstallUninstallDebugString" option to display a message when
+ FastMM is installed or uninstalled. (Thanks to Hanspeter Widmer.)
+ - Moved the options to a separate include file. (Thanks to Hanspeter Widmer.)
+ - Moved message strings to a separate file for easy translation.
+ Version 4.19 (19 July 2005):
+ - Fixed Kylix support that was broken in 4.14.
+ Version 4.20 (20 July 2005):
+ - Fixed a false memory overwrite report at shutdown in "FullDebugMode". If you
+ consistently got a "Block Header Has Been Corrupted" error message during
+ shutdown at address $xxxx0070 then it was probably a false alarm. (Thanks to
+ Theo Carr-Brion and Hanspeter Widmer.}
+ Version 4.21 (27 July 2005):
+ - Minor change to the block header flags to make it possible to immediately
+ tell whether a medium block is being used as a small block pool or not.
+ (Simplifies the leak checking and status reporting code.)
+ - Expanded the functionality around the management of expected memory leaks.
+ - Added the "ClearLogFileOnStartup" option. Deletes the log file during
+ initialization. (Thanks to M. Skloff.)
+ - Changed "OutputInstallUninstallDebugString" to use OutputDebugString instead
+ of MessageBox. (Thanks to Hanspeter Widmer.)
+ Version 4.22 (1 August 2005):
+ - Added a FastAllocMem function that avoids an unnecessary FillChar call with
+ large blocks.
+ - Changed large block resizing behavior to be a bit more conservative. Large
+ blocks will be downsized if the new size is less than half of the old size
+ (the threshold was a quarter previously).
+ Version 4.23 (6 August 2005):
+ - Fixed BCB6 support (Thanks to Omar Zelaya).
+ - Renamed "OutputInstallUninstallDebugString" to "UseOutputDebugString", and
+ added debug string output on memory leak or error detection.
+ Version 4.24 (11 August 2005):
+ - Added the "NoMessageBoxes" option to suppress the display of message boxes,
+ which is useful for services that should not be interrupted. (Thanks to Dan
+ Miser).
+ - Changed the stack trace code to return the line number of the caller and not
+ the line number of the return address. (Thanks to Dan Miser).
+ Version 4.25 (15 August 2005):
+ - Fixed GetMemoryLeakType not detecting expected leaks registered by class
+ when in "FullDebugMode". (Thanks to Arjen de Ruijter).
+ Version 4.26 (18 August 2005):
+ - Added a "UseRuntimePackages" option that allows FastMM to be used in a main
+ application together with DLLs that all use runtime packages. (Thanks to
+ Aleksander Oven.)
+ Version 4.27 (24 August 2005):
+ - Fixed a bug that sometimes caused the leak report to be shown even though all
+ leaks were registered as expected leaks. (Thanks to Kristofer Skaug.)
+ Version 4.29 (30 September 2005):
+ - Added the "RequireDebuggerPresenceForLeakReporting" option to only display
+ the leak report if the application is run inside the IDE. (Thanks to G\xFCnther
+ Schoch.)
+ - Added the "ForceMMX" option, which when disabled will check the CPU for
+ MMX compatibility before using MMX. (Thanks to Jan Schl\xFCter.)
+ - Added the module name to the title of error dialogs to more easily identify
+ which application caused the error. (Thanks to Kristofer Skaug.)
+ - Added an ASCII dump to the "FullDebugMode" memory dumps. (Thanks to Hallvard
+ Vassbotn.)
+ - Added the option "HideExpectedLeaksRegisteredByPointer" to suppress the
+ display and logging of expected memory leaks that were registered by pointer.
+ (Thanks to Dan Miser.) Leaks registered by size or class are often ambiguous,
+ so these expected leaks are always logged to file (in FullDebugMode) and are
+ never hidden from the leak display (only displayed if there is at least one
+ unexpected leak).
+ - Added a procedure "GetRegisteredMemoryLeaks" to return a list of all
+ registered memory leaks. (Thanks to Dan Miser.)
+ - Added the "RawStackTraces" option to perform "raw" stack traces, negating
+ the need for stack frames. This will usually result in more complete stack
+ traces in FullDebugMode error reports, but it is significantly slower.
+ (Thanks to Hallvard Vassbotn, Dan Miser and the JCL team.)
+ Version 4.31 (2 October 2005):
+ - Fixed the crash bug when both "RawStackTraces" and "FullDebugMode" were
+ enabled. (Thanks to Dan Miser and Mark Edington.)
+ Version 4.33 (6 October 2005):
+ - Added a header corruption check to all memory blocks that are identified as
+ leaks in FullDebugMode. This allows better differentiation between memory
+ pool corruption bugs and actual memory leaks.
+ - Fixed the stack overflow bug when using "RawStackTraces".
+ Version 4.35 (6 October 2005):
+ - Fixed a compilation error when the "NoMessageBoxes" option is set. (Thanks
+ to Paul Ishenin.)
+ - Before performing a "raw" stack trace, FastMM now checks whether exception
+ handling is in place. If exception handling is not in place FastMM falls
+ back to stack frame tracing. (Exception handling is required to handle the
+ possible A/Vs when reading invalid call addresses. Exception handling is
+ usually always available except when SysUtils hasn't been initialized yet or
+ after SysUtils has been finalized.)
+ Version 4.37 (8 October 2005):
+ - Fixed the missing call stack trace entry issue when dynamically loading DLLs.
+ (Thanks to Paul Ishenin.)
+ Version 4.39 (12 October 2005):
+ - Restored the performance with "RawStackTraces" enabled back to the level it
+ was in 4.35.
+ - Fixed the stack overflow error when using "RawStackTraces" that I thought I
+ had fixed in 4.31, but unfortunately didn't. (Thanks to Craig Peterson.)
+ Version 4.40 (13 October 2005):
+ - Improved "RawStackTraces" to have less incorrect extra entries. (Thanks to
+ Craig Peterson.)
+ - Added the Russian (by Paul Ishenin) and Afrikaans translations of
+ FastMM4Messages.pas.
+ Version 4.42 (13 October 2005):
+ - Fixed the compilation error when "CatchUseOfFreedInterfaces" is enabled.
+ (Thanks to Cristian Nicola.)
+ Version 4.44 (25 October 2005):
+ - Implemented a FastGetHeapStatus function in analogy with GetHeapStatus.
+ (Suggested by Cristian Nicola.)
+ - Shifted more of the stack trace code over to the support dll to allow third
+ party vendors to make available their own stack tracing and stack trace
+ logging facilities.
+ - Mathias Rauen (madshi) improved the support for madExcept in the debug info
+ support DLL. Thanks!
+ - Added support for BCB5. (Thanks to Roddy Pratt.)
+ - Added the Czech translation by Rene Mihula.
+ - Added the "DetectMMOperationsAfterUninstall" option. This will catch
+ attempts to use the MM after FastMM has been uninstalled, and is useful for
+ debugging.
+ Version 4.46 (26 October 2005):
+ - Renamed FastMM_DebugInfo.dll to FastMM_FullDebugMode.dll and made the
+ dependency on this library a static one. This solves a DLL unload order
+ problem when using FullDebugMode together with the replacement
+ borlndmm.dll. (Thanks to Bart van der Werf.)
+ - Added the Polish translation by Artur Redzko.
+ Version 4.48 (10 November 2005):
+ - Fixed class detection for objects leaked in dynamically loaded DLLs that
+ were relocated.
+ - Fabio Dell'Aria implemented support for EurekaLog in the FullDebugMode
+ support DLL. Thanks!
+ - Added the Spanish translation by JRG ("The Delphi Guy").
+ Version 4.49 (10 November 2005):
+ - Implemented support for installing replacement AllocMem and leak
+ registration mechanisms for Delphi/BCB versions that support it.
+ - Added support for Delphi 4. (Thanks to Justus Janssen.)
+ Version 4.50 (5 December 2005):
+ - Renamed the ReportMemoryLeaks global variable to ReportMemoryLeaksOnShutdown
+ to be more consistent with the Delphi 2006 memory manager.
+ - Improved the handling of large blocks. Large blocks can now consist of
+ several consecutive segments allocated through VirtualAlloc. This
+ significantly improves speed when frequently resizing large blocks, since
+ these blocks can now often be upsized in-place.
+ Version 4.52 (7 December 2005):
+ - Fixed the compilation error with Delphi 5. (Thanks to Vadim Lopushansky and
+ Charles Vinal for reporting the error.)
+ Version 4.54 (15 December 2005):
+ - Added the Brazilian Portuguese translation by Johni Jeferson Capeletto.
+ - Fixed the compilation error with BCB6. (Thanks to Kurt Fitzner.)
+ Version 4.56 (20 December 2005):
+ - Fixed the Kylix compilation problem. (Thanks to Michal Niklas.)
+ Version 4.58 (1 February 2006):
+ - Added the German translations by Thomas Speck and Uwe Queisser.
+ - Added the Indonesian translation by Zaenal Mutaqin.
+ - Added the Portuguese translation by Carlos Macao.
+ Version 4.60 (21 February 2006):
+ - Fixed a performance issue due to an unnecessary block move operation when
+ allocating a block in the range 1261-1372 bytes and then reallocating it in
+ the range 1373-1429 bytes twice. (Thanks to Michael Winter.)
+ - Added the Belarussian translation by dzmitry[li].
+ - Added the updated Spanish translation by Marcelo Montenegro.
+ - Added a new option "EnableSharingWithDefaultMM". This option allows FastMM
+ to be shared with the default MM of Delphi 2006. It is on by default, but
+ MM sharing has to be enabled otherwise it has no effect (refer to the
+ documentation for the "ShareMM" and "AttemptToUseSharedMM" options).
+ Version 4.62 (22 February 2006):
+ - Fixed a possible read access violation in the MoveX16L4 routine when the
+ UseCustomVariableSizeMoveRoutines option is enabled. (Thanks to Jud Cole for
+ some great detective work in finding this bug.)
+ - Improved the downsizing behaviour of medium blocks to better correlate with
+ the reallocation behaviour of small blocks. This change reduces the number
+ of transitions between small and medium block types when reallocating blocks
+ in the 0.7K to 2.6K range. It cuts down on the number of memory move
+ operations and improves performance.
+ Version 4.64 (31 March 2006):
+ - Added the following functions for use with FullDebugMode (and added the
+ exports to the replacement BorlndMM.dll): SetMMLogFileName,
+ GetCurrentAllocationGroup, PushAllocationGroup, PopAllocationGroup and
+ LogAllocatedBlocksToFile. The purpose of these functions are to allow you to
+ identify and log related memory leaks while your application is still
+ running.
+ - Fixed a bug in the memory manager sharing mechanism affecting Windows
+ 95/98/ME. (Thanks to Zdenek Vasku.)
+ Version 4.66 (9 May 2006):
+ - Added a hint comment in this file so that FastMM4Messages.pas will also be
+ backed up by GExperts. (Thanks to RB Winston.)
+ - Fixed a bug affecting large address space (> 2GB) support under
+ FullDebugMode. (Thanks to Thomas Schulz.)
+ Version 4.68 (3 July 2006):
+ - Added the Italian translation by Luigi Sandon.
+ - If FastMM is used inside a DLL it will now use the name of the DLL as base
+ for the log file name. (Previously it always used the name of the main
+ application executable file.)
+ - Fixed a rare A/V when both the FullDebugMode and RawStackTraces options were
+ enabled. (Thanks to Primoz Gabrijelcic.)
+ - Added the "NeverSleepOnThreadContention" option. This option may improve
+ performance if the ratio of the the number of active threads to the number
+ of CPU cores is low (typically < 2). This option is only useful for 4+ CPU
+ systems, it almost always hurts performance on single and dual CPU systems.
+ (Thanks to Werner Bochtler and Markus Beth.)
+ Version 4.70 (4 August 2006):
+ - Added the Simplified Chinese translation by JiYuan Xie.
+ - Added the updated Russian as well as the Ukrainian translation by Andrey
+ Shtukaturov.
+ - Fixed two bugs in the leak class detection code that would sometimes fail
+ to detect the class of leaked objects and strings, and report them as
+ 'unknown'. (Thanks to Dimitry Timokhov)
+ Version 4.72 (24 September 2006):
+ - Fixed a bug that caused AllocMem to not clear blocks > 256K in
+ FullDebugMode. (Thanks to Paulo Moreno.)
+ Version 4.74 (9 November 2006):
+ - Fixed a bug in the segmented large block functionality that could lead to
+ an application freeze when upsizing blocks greater than 256K in a
+ multithreaded application (one of those "what the heck was I thinking?"
+ type bugs).
+
+*)
+
+unit FastMM4;
+
+interface
+
+{$Include FastMM4Options.inc}
+
+{$RANGECHECKS OFF}
+{$BOOLEVAL OFF}
+{$OVERFLOWCHECKS OFF}
+{$OPTIMIZATION ON}
+{$TYPEDADDRESS OFF}
+
+{Some features not currently supported under Kylix}
+{$ifdef Linux}
+ {$undef LogErrorsToFile}
+ {$undef LogMemoryLeakDetailToFile}
+ {$undef ShareMM}
+ {$undef AttemptToUseSharedMM}
+ {$undef RequireIDEPresenceForLeakReporting}
+ {$undef UseOutputDebugString}
+{$endif}
+
+{Do we require debug info for leak checking?}
+{$ifdef RequireDebugInfoForLeakReporting}
+ {$ifopt D-}
+ {$undef EnableMemoryLeakReporting}
+ {$endif}
+{$endif}
+
+{Enable heap checking and leak reporting in full debug mode}
+{$ifdef FullDebugMode}
+ {$STACKFRAMES ON}
+ {$define CheckHeapForCorruption}
+ {$ifndef CatchUseOfFreedInterfaces}
+ {$define CheckUseOfFreedBlocksOnShutdown}
+ {$endif}
+{$else}
+ {Error logging requires FullDebugMode}
+ {$undef LogErrorsToFile}
+ {$undef CatchUseOfFreedInterfaces}
+ {$undef RawStackTraces}
+{$endif}
+
+{Only the pascal version supports extended heap corruption checking.}
+{$ifdef CheckHeapForCorruption}
+ {$undef ASMVersion}
+{$endif}
+
+{$ifdef UseRuntimePackages}
+ {$define AssumeMultiThreaded}
+{$endif}
+
+{Delphi versions}
+{$ifndef BCB}
+ {$ifdef ver120}
+ {$define Delphi4or5}
+ {$endif}
+ {$ifdef ver130}
+ {$define Delphi4or5}
+ {$endif}
+ {$ifdef ver140}
+ {$define Delphi6}
+ {$endif}
+ {$ifdef ver150}
+ {$define Delphi7}
+ {$endif}
+ {$ifdef ver170}
+ {$define Delphi2005}
+ {$endif}
+{$else}
+ {Cannot uninstall safely under BCB}
+ {$define NeverUninstall}
+ {Disable memory leak reporting}
+ {$undef EnableMemoryLeakReporting}
+ {for BCB5, use the Delphi 5 codepath}
+ {$ifdef ver130}
+ {$define Delphi4or5}
+ {$endif}
+{$endif}
+{$ifdef ver180}
+ {$define BDS2006}
+{$endif}
+
+{$ifndef Delphi4or5}
+ {$ifndef BCB}
+ {$define Delphi6AndUp}
+ {$endif}
+ {$ifndef Delphi6}
+ {$define BCB6OrDelphi7AndUp}
+ {$ifndef BCB}
+ {$define Delphi7AndUp}
+ {$endif}
+ {$ifndef BCB}
+ {$ifndef Delphi7}
+ {$ifndef Delphi2005}
+ {$define BDS2006AndUp}
+ {$endif}
+ {$endif}
+ {$endif}
+ {$endif}
+{$endif}
+
+{$ifdef Delphi6AndUp}
+ {$WARN SYMBOL_PLATFORM OFF}
+ {$WARN SYMBOL_DEPRECATED OFF}
+{$endif}
+
+{Leak detail logging requires error logging}
+{$ifndef LogErrorsToFile}
+ {$undef LogMemoryLeakDetailToFile}
+ {$undef ClearLogFileOnStartup}
+{$endif}
+
+{$ifndef EnableMemoryLeakReporting}
+ {Manual leak reporting control requires leak reporting to be enabled}
+ {$undef ManualLeakReportingControl}
+{$endif}
+
+{$ifndef EnableMMX}
+ {$undef ForceMMX}
+{$endif}
+
+{Instruct GExperts to back up the messages file as well.}
+{#BACKUP FastMM4Messages.pas}
+
+{-------------------------Public constants-----------------------------}
+const
+ {The number of small block types}
+{$ifdef Align16Bytes}
+ NumSmallBlockTypes = 46;
+{$else}
+ NumSmallBlockTypes = 55;
+{$endif}
+
+{----------------------------Public types------------------------------}
+type
+ TSmallBlockTypeState = packed record
+ {The internal size of the block type}
+ InternalBlockSize: Cardinal;
+ {Useable block size: The number of non-reserved bytes inside the block.}
+ UseableBlockSize: Cardinal;
+ {The number of allocated blocks}
+ AllocatedBlockCount: Cardinal;
+ {The total address space reserved for this block type (both allocated and
+ free blocks)}
+ ReservedAddressSpace: Cardinal;
+ end;
+ TSmallBlockTypeStates = array[0..NumSmallBlockTypes - 1] of TSmallBlockTypeState;
+
+ TMemoryManagerState = packed record
+ {Small block type states}
+ SmallBlockTypeStates: TSmallBlockTypeStates;
+ {Medium block stats}
+ AllocatedMediumBlockCount: Cardinal;
+ TotalAllocatedMediumBlockSize: Cardinal;
+ ReservedMediumBlockAddressSpace: Cardinal;
+ {Large block stats}
+ AllocatedLargeBlockCount: Cardinal;
+ TotalAllocatedLargeBlockSize: Cardinal;
+ ReservedLargeBlockAddressSpace: Cardinal;
+ end;
+
+ {Memory map}
+ TChunkStatus = (csUnallocated, csAllocated, csReserved,
+ csSysAllocated, csSysReserved);
+ TMemoryMap = array[0..65535] of TChunkStatus;
+
+{$ifdef EnableMemoryLeakReporting}
+ {List of registered leaks}
+ TRegisteredMemoryLeak = packed record
+ LeakAddress: Pointer;
+ LeakedClass: TClass;
+ LeakSize: Integer;
+ LeakCount: Integer;
+ end;
+ TRegisteredMemoryLeaks = array of TRegisteredMemoryLeak;
+{$endif}
+
+{--------------------------Public variables----------------------------}
+{$ifdef ManualLeakReportingControl}
+ {Variable is declared in system.pas in newer Delphi versions.}
+ {$ifndef BDS2006AndUp}
+var
+ ReportMemoryLeaksOnShutdown: Boolean;
+ {$endif}
+{$endif}
+
+{-------------------------Public procedures----------------------------}
+{Installation procedures must be exposed for the BCB helper unit FastMM4BCB.cpp}
+{$ifdef BCB}
+procedure InitializeMemoryManager;
+function CheckCanInstallMemoryManager: boolean;
+procedure InstallMemoryManager;
+{$endif}
+
+{$ifndef FullDebugMode}
+{The standard memory manager functions}
+function FastGetMem(ASize: Integer): Pointer;
+function FastFreeMem(APointer: Pointer): Integer;
+function FastReallocMem(APointer: Pointer; ANewSize: Integer): Pointer;
+function FastAllocMem(ASize: Cardinal): Pointer;
+{$else}
+{The FullDebugMode memory manager functions}
+function DebugGetMem(ASize: Integer): Pointer;
+function DebugFreeMem(APointer: Pointer): Integer;
+function DebugReallocMem(APointer: Pointer; ANewSize: Integer): Pointer;
+function DebugAllocMem(ASize: Cardinal): Pointer;
+{Specify the full path and name for the filename to be used for logging memory
+ errors, etc. If ALogFileName is nil or points to an empty string it will
+ revert to the default log file name.}
+procedure SetMMLogFileName(ALogFileName: PChar = nil);
+{Returns the current "allocation group". Whenever a GetMem request is serviced
+ in FullDebugMode, the current "allocation group" is stored in the block header.
+ This may help with debugging. Note that if a block is subsequently reallocated
+ that it keeps its original "allocation group" and "allocation number" (all
+ allocations are also numbered sequentially).}
+function GetCurrentAllocationGroup: Cardinal;
+{Allocation groups work in a stack like fashion. Group numbers are pushed onto
+ and popped off the stack. Note that the stack size is limited, so every push
+ should have a matching pop.}
+procedure PushAllocationGroup(ANewCurrentAllocationGroup: Cardinal);
+procedure PopAllocationGroup;
+{Logs detail about currently allocated memory blocks for the specified range of
+ allocation groups. if ALastAllocationGroupToLog is less than
+ AFirstAllocationGroupToLog or it is zero, then all allocation groups are
+ logged. This routine also checks the memory pool for consistency at the same
+ time.}
+procedure LogAllocatedBlocksToFile(AFirstAllocationGroupToLog, ALastAllocationGroupToLog: Cardinal);
+{$endif}
+
+{Releases all allocated memory (use with extreme care)}
+procedure FreeAllMemory;
+
+{Returns summarised information about the state of the memory manager. (For
+ backward compatibility.)}
+function FastGetHeapStatus: THeapStatus;
+{Returns statistics about the current state of the memory manager}
+procedure GetMemoryManagerState(var AMemoryManagerState: TMemoryManagerState);
+{$ifndef LINUX}
+{Gets the state of every 64K block in the 4GB address space}
+procedure GetMemoryMap(var AMemoryMap: TMemoryMap);
+{$endif}
+
+{$ifdef EnableMemoryLeakReporting}
+{Registers expected memory leaks. Returns true on success. The list of leaked
+ blocks is limited, so failure is possible if the list is full.}
+function RegisterExpectedMemoryLeak(ALeakedPointer: Pointer): boolean; overload;
+function RegisterExpectedMemoryLeak(ALeakedObjectClass: TClass; ACount: Integer = 1): boolean; overload;
+function RegisterExpectedMemoryLeak(ALeakedBlockSize: Integer; ACount: Integer = 1): boolean; overload;
+{Removes expected memory leaks. Returns true on success.}
+function UnregisterExpectedMemoryLeak(ALeakedPointer: Pointer): boolean; overload;
+function UnregisterExpectedMemoryLeak(ALeakedObjectClass: TClass; ACount: Integer = 1): boolean; overload;
+function UnregisterExpectedMemoryLeak(ALeakedBlockSize: Integer; ACount: Integer = 1): boolean; overload;
+{Returns a list of all expected memory leaks}
+function GetRegisteredMemoryLeaks: TRegisteredMemoryLeaks;
+{$endif}
+
+implementation
+
+uses
+{$ifndef Linux}
+ Windows,
+{$else}
+ Libc,
+{$endif}
+ FastMM4Messages;
+
+{Fixed size move procedures}
+procedure Move12(const ASource; var ADest; ACount: Integer); forward;
+procedure Move20(const ASource; var ADest; ACount: Integer); forward;
+procedure Move28(const ASource; var ADest; ACount: Integer); forward;
+procedure Move36(const ASource; var ADest; ACount: Integer); forward;
+procedure Move44(const ASource; var ADest; ACount: Integer); forward;
+procedure Move52(const ASource; var ADest; ACount: Integer); forward;
+procedure Move60(const ASource; var ADest; ACount: Integer); forward;
+procedure Move68(const ASource; var ADest; ACount: Integer); forward;
+
+{$ifdef DetectMMOperationsAfterUninstall}
+{Invalid handlers to catch MM operations after uninstall}
+function InvalidFreeMem(APointer: Pointer): Integer; forward;
+function InvalidGetMem(ASize: Integer): Pointer; forward;
+function InvalidReallocMem(APointer: Pointer; ANewSize: Integer): Pointer; forward;
+function InvalidAllocMem(ASize: Cardinal): Pointer; forward;
+function InvalidRegisterAndUnRegisterMemoryLeak(APointer: Pointer): Boolean; forward;
+{$endif}
+
+{-------------------------Private constants----------------------------}
+const
+ {The size of a medium block pool. This is allocated through VirtualAlloc and
+ is used to serve medium blocks. The size must be a multiple of 16 and at
+ least 4 bytes less than a multiple of 4K (the page size) to prevent a
+ possible read access violation when reading past the end of a memory block
+ in the optimized move routine (MoveX16L4). In Full Debug mode we leave a
+ trailing 256 bytes to be able to safely do a memory dump.}
+ MediumBlockPoolSize = 20 * 64 * 1024{$ifndef FullDebugMode} - 16{$else} - 256{$endif};
+ {The granularity of small blocks}
+{$ifdef Align16Bytes}
+ SmallBlockGranularity = 16;
+{$else}
+ SmallBlockGranularity = 8;
+{$endif}
+ {The granularity of medium blocks. Newly allocated medium blocks are
+ a multiple of this size plus MediumBlockSizeOffset, to avoid cache line
+ conflicts}
+ MediumBlockGranularity = 256;
+ MediumBlockSizeOffset = 48;
+ {The granularity of large blocks}
+ LargeBlockGranularity = 65536;
+ {The maximum size of a small block. Blocks Larger than this are either
+ medium or large blocks.}
+ MaximumSmallBlockSize = 2608;
+ {The smallest medium block size. (Medium blocks are rounded up to the nearest
+ multiple of MediumBlockGranularity plus MediumBlockSizeOffset)}
+ MinimumMediumBlockSize = 11 * 256 + MediumBlockSizeOffset;
+ {The number of bins reserved for medium blocks}
+ MediumBlockBinsPerGroup = 32;
+ MediumBlockBinGroupCount = 32;
+ MediumBlockBinCount = MediumBlockBinGroupCount * MediumBlockBinsPerGroup;
+ {The maximum size allocatable through medium blocks. Blocks larger than this
+ fall through to VirtualAlloc ( = large blocks).}
+ MaximumMediumBlockSize = MinimumMediumBlockSize + (MediumBlockBinCount - 1) * MediumBlockGranularity;
+ {The target number of small blocks per pool. The actual number of blocks per
+ pool may be much greater for very small sizes and less for larger sizes. The
+ cost of allocating the small block pool is amortized across all the small
+ blocks in the pool, however the blocks may not all end up being used so they
+ may be lying idle.}
+ TargetSmallBlocksPerPool = 48;
+ {The minimum number of small blocks per pool. Any available medium block must
+ have space for roughly this many small blocks (or more) to be useable as a
+ small block pool.}
+ MinimumSmallBlocksPerPool = 12;
+ {The lower and upper limits for the optimal small block pool size}
+ OptimalSmallBlockPoolSizeLowerLimit = 29 * 1024 - MediumBlockGranularity + MediumBlockSizeOffset;
+ OptimalSmallBlockPoolSizeUpperLimit = 64 * 1024 - MediumBlockGranularity + MediumBlockSizeOffset;
+ {The maximum small block pool size. If a free block is this size or larger
+ then it will be split.}
+ MaximumSmallBlockPoolSize = OptimalSmallBlockPoolSizeUpperLimit + MinimumMediumBlockSize;
+ {-------------Block type flags--------------}
+ {The lower 3 bits in the dword header of small blocks (4 bits in medium and
+ large blocks) are used as flags to indicate the state of the block}
+ {Set if the block is not in use}
+ IsFreeBlockFlag = 1;
+ {Set if this is a medium block}
+ IsMediumBlockFlag = 2;
+ {Set if it is a medium block being used as a small block pool. Only valid if
+ IsMediumBlockFlag is set.}
+ IsSmallBlockPoolInUseFlag = 4;
+ {Set if it is a large block. Only valid if IsMediumBlockFlag is not set.}
+ IsLargeBlockFlag = 4;
+ {Is the medium block preceding this block available? (Only used by medium
+ blocks)}
+ PreviousMediumBlockIsFreeFlag = 8;
+ {Is this large block segmented? I.e. is it actually built up from more than
+ one chunk allocated through VirtualAlloc? (Only used by large blocks.)}
+ LargeBlockIsSegmented = 8;
+ {The flags masks for small blocks}
+ DropSmallFlagsMask = -8;
+ ExtractSmallFlagsMask = 7;
+ {The flags masks for medium and large blocks}
+ DropMediumAndLargeFlagsMask = -16;
+ ExtractMediumAndLargeFlagsMask = 15;
+ {-------------Block resizing constants---------------}
+ SmallBlockDownsizeCheckAdder = 64;
+ SmallBlockUpsizeAdder = 32;
+ {When a medium block is reallocated to a size smaller than this, then it must
+ be reallocated to a small block and the data moved. If not, then it is
+ shrunk in place down to MinimumMediumBlockSize. Currently the limit is set
+ at a quarter of the minimum medium block size.}
+ MediumInPlaceDownsizeLimit = MinimumMediumBlockSize div 4;
+ {-------------Memory leak reporting constants---------------}
+ ExpectedMemoryLeaksListSize = 64 * 1024;
+ {-------------FullDebugMode constants---------------}
+{$ifdef FullDebugMode}
+ {The stack trace depth}
+ StackTraceDepth = 9;
+ {The number of entries in the allocation group stack}
+ AllocationGroupStackSize = 1000;
+ {The number of fake VMT entries - used to track virtual method calls on
+ freed objects. Do not change this value without also updating TFreedObject.GetVirtualMethodIndex}
+ MaxFakeVMTEntries = 200;
+ {The pattern used to fill unused memory}
+ DebugFillByte = $80;
+ DebugFillDWord = $01010101 * Cardinal(DebugFillByte);
+ {The address that is reserved so that accesses to the address of the fill
+ pattern will result in an A/V}
+ DebugReservedAddress = $01010000 * Cardinal(DebugFillByte);
+{$endif}
+ {-------------Other constants---------------}
+{$ifndef NeverSleepOnThreadContention}
+ {Sleep time when a resource (small/medium/large block manager) is in use}
+ InitialSleepTime = 0;
+ {Used when the resource is still in use after the first sleep}
+ AdditionalSleepTime = 10;
+{$endif}
+ {Hexadecimal characters}
+ HexTable: array[0..15] of char = '0123456789ABCDEF';
+ {Copyright message - not used anywhere in the code}
+ Copyright: string = 'FastMM4 \xA9 2004, 2005, 2006 Pierre le Riche / Professional Software Development';
+
+{-------------------------Private types----------------------------}
+type
+
+{$ifdef Delphi4or5}
+ {Delphi 5 Compatibility}
+ PCardinal = ^Cardinal;
+ PPointer = ^Pointer;
+{$endif}
+
+ {Move procedure type}
+ TMoveProc = procedure(const ASource; var ADest; ACount: Integer);
+
+ {Registers structure (for GetCPUID)}
+ TRegisters = record
+ RegEAX, RegEBX, RegECX, RegEDX: Integer;
+ end;
+
+{$ifdef EnableMemoryLeakReporting}
+ {Different kinds of memory leaks}
+ TMemoryLeakType = (mltUnexpectedLeak, mltExpectedLeakRegisteredByPointer,
+ mltExpectedLeakRegisteredByClass, mltExpectedLeakRegisteredBySize);
+{$endif}
+
+ {---------------Small block structures-------------}
+
+ {Pointer to the header of a small block pool}
+ PSmallBlockPoolHeader = ^TSmallBlockPoolHeader;
+
+ {Small block type (Size = 32)}
+ PSmallBlockType = ^TSmallBlockType;
+ TSmallBlockType = packed record
+ {True = Block type is locked}
+ BlockTypeLocked: boolean;
+ {Bitmap indicating which of the first 8 medium block groups contain blocks
+ of a suitable size for a block pool.}
+ AllowedGroupsForBlockPoolBitmap: byte;
+ {The block size for this block type}
+ BlockSize: Word;
+ {The first partially free pool for the given small block type (offset = +4
+ for typecast compatibility with TSmallBlockPoolHeader). This is a circular
+ buffer.}
+ NextPartiallyFreePool: PSmallBlockPoolHeader;
+ {The offset of the last block that was served sequentially (0ffset = +8 to
+ to be at the same offset as the "FirstFreeBlock" of TSmallBlockPoolHeader}
+ NextSequentialFeedBlockAddress: Pointer;
+ {The last block that can be served sequentially. Offset is at +12 to be
+ at the same address as the "BlocksInUse" field of TSmallBlockPoolHeader}
+ MaxSequentialFeedBlockAddress: Pointer;
+ {The pool that is current being used to serve blocks in sequential order}
+ CurrentSequentialFeedPool: PSmallBlockPoolHeader;
+ {The previous partially free pool for the small block type (offset = +20
+ for typecast compatibility with TSmallBlockPoolHeader)}
+ PreviousPartiallyFreePool: PSmallBlockPoolHeader;
+ {The minimum and optimal size of a small block pool for this block type}
+ MinimumBlockPoolSize: Word;
+ OptimalBlockPoolSize: Word;
+{$ifdef UseCustomFixedSizeMoveRoutines}
+ {The fixed size move procedure used to move data for this block size when
+ it is upsized. When a block is downsized (which usually does not occur
+ that often) the variable size move routine is used.}
+ UpsizeMoveProcedure: TMoveProc;
+{$else}
+ Reserved1: Cardinal;
+{$endif}
+ end;
+
+ {Small block pool (Size = 32 bytes)}
+ TSmallBlockPoolHeader = packed record
+ {BlockType}
+ BlockType: PSmallBlockType;
+ {The next pool that has free blocks of this size. Must be at offset +4
+ to be typecast compatible with TSmallBlockType}
+ NextPartiallyFreePool: PSmallBlockPoolHeader;
+ {Pointer to the first free block inside this pool. Must be at offset + 8
+ to be at the same offset as "NextSequentialFeedBlockAddress" of
+ TSmallBlockType}
+ FirstFreeBlock: Pointer;
+ {The number of blocks allocated in this pool. Must be at offset + 12
+ to be at the same offset as "MaxSequentialFeedBlockAddress" of
+ TSmallBlockType}
+ BlocksInUse: Cardinal;
+ {Reserved}
+ Reserved1: Cardinal;
+ {The previous pool that has free blocks of this size. Must be at offset +20
+ to be compatible with TSmallBlockType}
+ PreviousPartiallyFreePool: PSmallBlockPoolHeader;
+ {Reserved}
+ Reserved2: Cardinal;
+ {The pool pointer and flags of the first block}
+ FirstBlockPoolPointerAndFlags: Cardinal;
+ end;
+
+ {Small block layout:
+ Offset: -4 = Flags + address of the small block pool
+ Offset: BlockSize - 4 = Flags + address of the small block pool for the next small block
+ }
+
+ {----------------------Medium block structures----------------------}
+
+ {The medium block pool from which medium blocks are drawn}
+ PMediumBlockPoolHeader = ^TMediumBlockPoolHeader;
+ TMediumBlockPoolHeader = packed record
+ {Points to the previous and next medium block pools. This circular linked
+ list is used to track memory leaks on program shutdown.}
+ PreviousMediumBlockPoolHeader: PMediumBlockPoolHeader;
+ NextMediumBlockPoolHeader: PMediumBlockPoolHeader;
+ {Unused dword}
+ Reserved: Cardinal;
+ {The block size and flags of the first medium block in the block pool}
+ FirstMediumBlockSizeAndFlags: Cardinal;
+ end;
+
+ {Medium block layout:
+ Offset: -8 = Previous Block Size (only if the previous block is free)
+ Offset: -4 = This block size and flags
+ Offset: 0 = User data / Previous Free Block (if this block is free)
+ Offset: 4 = Next Free Block (if this block is free)
+ Offset: BlockSize - 8 = Size of this block (if this block is free)
+ Offset: BlockSize - 4 = Size of the next block and flags
+
+ {A medium block that is unused}
+ PMediumFreeBlock = ^TMediumFreeBlock;
+ TMediumFreeBlock = packed record
+ PreviousFreeBlock: PMediumFreeBlock;
+ NextFreeBlock: PMediumFreeBlock;
+ end;
+
+ {-------------------------Large block structures--------------------}
+
+ {Large block header record (size = 16)}
+ PLargeBlockHeader = ^TLargeBlockHeader;
+ TLargeBlockHeader = packed record
+ {Points to the previous and next large blocks. This circular linked
+ list is used to track memory leaks on program shutdown.}
+ PreviousLargeBlockHeader: PLargeBlockHeader;
+ NextLargeBlockHeader: PLargeBlockHeader;
+ {The user allocated size of the Large block}
+ UserAllocatedSize: Cardinal;
+ {The size of this block plus the flags}
+ BlockSizeAndFlags: Cardinal;
+ end;
+
+ {-------------------------Expected Memory Leak Structures--------------------}
+{$ifdef EnableMemoryLeakReporting}
+
+ {The layout of an expected leak. All fields may not be specified, in which
+ case it may be harder to determine which leaks are expected and which are
+ not.}
+ PExpectedMemoryLeak = ^TExpectedMemoryLeak;
+ PPExpectedMemoryLeak = ^PExpectedMemoryLeak;
+ TExpectedMemoryLeak = packed record
+ {Linked list pointers}
+ PreviousLeak, NextLeak: PExpectedMemoryLeak;
+ {Information about the expected leak}
+ LeakAddress: Pointer;
+ LeakedClass: TClass;
+ LeakSize: Integer;
+ LeakCount: Integer;
+ end;
+
+ TExpectedMemoryLeaks = packed record
+ {The number of entries used in the expected leaks buffer}
+ EntriesUsed: Integer;
+ {Freed entries}
+ FirstFreeSlot: PExpectedMemoryLeak;
+ {Entries with the address specified}
+ FirstEntryByAddress: PExpectedMemoryLeak;
+ {Entries with no address specified, but with the class specified}
+ FirstEntryByClass: PExpectedMemoryLeak;
+ {Entries with only size specified}
+ FirstEntryBySizeOnly: PExpectedMemoryLeak;
+ {The expected leaks buffer}
+ ExpectedLeaks: packed array[0..(ExpectedMemoryLeaksListSize - 20) div SizeOf(TExpectedMemoryLeak) - 1] of TExpectedMemoryLeak;
+ end;
+ PExpectedMemoryLeaks = ^TExpectedMemoryLeaks;
+
+{$endif}
+
+ {-------------------------Full Debug Mode Structures--------------------}
+{$ifdef FullDebugMode}
+
+ PStackTrace = ^TStackTrace;
+ TStackTrace = array[0..StackTraceDepth - 1] of Cardinal;
+
+ TBlockOperation = (boBlockCheck, boGetMem, boFreeMem, boReallocMem);
+
+ PFullDebugBlockHeader = ^TFullDebugBlockHeader;
+ TFullDebugBlockHeader = packed record
+ {Space used by the medium block manager for previous/next block management.
+ If a medium block is binned then these two dwords will be modified.}
+ Reserved1: Cardinal;
+ Reserved2: Cardinal;
+ {Is the block currently allocated?}
+ BlockInUse: LongBool;
+ {The allocation group: Can be used in the debugging process to group
+ related memory leaks together}
+ AllocationGroup: Cardinal;
+ {The allocation number: All new allocations are numbered sequentially. This
+ number may be useful in memory leak analysis. If it reaches 4GB it wraps
+ back to 0.}
+ AllocationNumber: Cardinal;
+ {The call stack when the block was allocated}
+ AllocationStackTrace: TStackTrace;
+ {The call stack when the block was freed}
+ FreeStackTrace: TStackTrace;
+ {The user requested size for the block. 0 if this is the first time the
+ block is used.}
+ UserSize: Cardinal;
+ {The object class this block was used for the previous time it was
+ allocated. When a block is freed, the dword that would normally be in the
+ space of the class pointer is copied here, so if it is detected that
+ the block was used after being freed we have an idea what class it is.}
+ PreviouslyUsedByClass: Cardinal;
+ {The sum of all the dwords excluding reserved dwords.}
+ HeaderCheckSum: Cardinal;
+ end;
+ {The last four bytes of the actual allocated block is the inverse of the
+ header checksum}
+
+ {The class used to catch attempts to execute a virtual method of a freed
+ object}
+ TFreedObject = class
+ public
+ procedure GetVirtualMethodIndex;
+ procedure VirtualMethodError;
+{$ifdef CatchUseOfFreedInterfaces}
+ procedure InterfaceError;
+{$endif}
+ end;
+
+{$endif}
+
+{-------------------------Private constants----------------------------}
+const
+{$ifndef BCB6OrDelphi7AndUp}
+ reInvalidPtr = 2;
+{$endif}
+ {The size of the block header in front of small and medium blocks}
+ BlockHeaderSize = 4;
+ {The size of a small block pool header}
+ SmallBlockPoolHeaderSize = SizeOf(TSmallBlockPoolHeader);
+ {The size of a medium block pool header}
+ MediumBlockPoolHeaderSize = SizeOf(TMediumBlockPoolHeader);
+ {The size of the header in front of Large blocks}
+ LargeBlockHeaderSize = SizeOf(TLargeBlockHeader);
+{$ifdef FullDebugMode}
+ {We need space for the header. 4 bytes for the trailer and 4 bytes for the
+ trailing block size when then block is free}
+ FullDebugBlockOverhead = SizeOf(TFullDebugBlockHeader) + 2 * SizeOf(Pointer);
+{$endif}
+
+{-------------------------Private variables----------------------------}
+var
+ {-----------------Small block management------------------}
+ {The small block types. Sizes include the leading 4-byte overhead. Sizes are
+ picked to limit maximum wastage to about 10% or 256 bytes (whichever is
+ less) where possible.}
+ SmallBlockTypes: packed array[0..NumSmallBlockTypes - 1] of TSmallBlockType =(
+ {8/16 byte jumps}
+ (BlockSize: 16 {$ifdef UseCustomFixedSizeMoveRoutines}; UpsizeMoveProcedure: Move12{$endif}),
+{$ifndef Align16Bytes}
+ (BlockSize: 24 {$ifdef UseCustomFixedSizeMoveRoutines}; UpsizeMoveProcedure: Move20{$endif}),
+{$endif}
+ (BlockSize: 32 {$ifdef UseCustomFixedSizeMoveRoutines}; UpsizeMoveProcedure: Move28{$endif}),
+{$ifndef Align16Bytes}
+ (BlockSize: 40 {$ifdef UseCustomFixedSizeMoveRoutines}; UpsizeMoveProcedure: Move36{$endif}),
+{$endif}
+ (BlockSize: 48 {$ifdef UseCustomFixedSizeMoveRoutines}; UpsizeMoveProcedure: Move44{$endif}),
+{$ifndef Align16Bytes}
+ (BlockSize: 56 {$ifdef UseCustomFixedSizeMoveRoutines}; UpsizeMoveProcedure: Move52{$endif}),
+{$endif}
+ (BlockSize: 64 {$ifdef UseCustomFixedSizeMoveRoutines}; UpsizeMoveProcedure: Move60{$endif}),
+{$ifndef Align16Bytes}
+ (BlockSize: 72 {$ifdef UseCustomFixedSizeMoveRoutines}; UpsizeMoveProcedure: Move68{$endif}),
+{$endif}
+ (BlockSize: 80),
+{$ifndef Align16Bytes}
+ (BlockSize: 88),
+{$endif}
+ (BlockSize: 96),
+{$ifndef Align16Bytes}
+ (BlockSize: 104),
+{$endif}
+ (BlockSize: 112),
+{$ifndef Align16Bytes}
+ (BlockSize: 120),
+{$endif}
+ (BlockSize: 128),
+{$ifndef Align16Bytes}
+ (BlockSize: 136),
+{$endif}
+ (BlockSize: 144),
+{$ifndef Align16Bytes}
+ (BlockSize: 152),
+{$endif}
+ (BlockSize: 160),
+ {16 byte jump...
[truncated message content] |