SomeObj.Free; SomeObj.SomeField := 1; // here: writing into released memorybut only in an application without EurekaLog. Once EurekaLog is added to an application, the FastMM no longer detects the "bad" code.
First of all: these kinds of checks highly depend on order in which memory operations are performed. FastMM does not detect writes into released memory as soon as the write operation completes. Instead, FastMM perform memory scanning check when your app request memory to be allocated in the same place - which can happen a lot later; or it could never happen at all.
For example:
SomeObj.Free; SomeObj.SomeField := 1; // this will not be detected TSomeObj.Create; // here: FastMM will allocate the object over the old memory block // and it will detect the old memory block was changed
Additionally, you can tell FastMM to force-scan all released memory via the
FastMM_ScanDebugBlocksForCorruption
function at any time.So one might think adding EurekaLog to an application changed the order of memory operations, so app's behaviour changed. However, that was not the case.
EurekaLog does not have its own memory manager. EurekaLog uses memory manager of your app - whatever it is set to. EurekaLog just adds some extra features to perform few memory checks. It is all done as layer on top of your existing memory manager. So, if you add FastMM to your project and then enable EurekaLog with memory checks - your app will use FastMM to allocate memory, while EurekaLog will use that memory to store extra data for memory checks.
The customer used FastMM 5. Unlike FastMM 4 (which enables full debug mode via conditional symbols), FastMM 5 can enable full debug mode by calling the
FastMM_EnterDebugMode
function. This function is so convenient, most people use it everytime, without realizing what it actually does.The way full debug mode in FastMM works is that it is actually two different memory managers: the "release" one (
FastMM_GetMem
) and full debug mode one (FastMM_DebugGetMem
). This was more obvious in FastMM 4, as enabling full debug mode required changing conditional symbols and a standalone DLL. So the FastMM_EnterDebugMode
function simply switches the FastMM_GetMem
to the FastMM_DebugGetMem
. What people don't realize is that it is only possible if your app still uses FastMM_GetMem
. Indeed: that way full debug mode will know how to release memory allocated by the FastMM_GetMem
.However, if memory manager was already set to something else (like EurekaLog's memory filter), the full debug mode would have no idea how to work with EurekaLog headers. Thus it won't be able to properly free memory allocated via EurekaLog. That is why the
FastMM_EnterDebugMode
function will no nothing when called in an application with EurekaLog (well, assuming it is called after EurekaLog's initialization). You can verify this:
if FastMM_EnterDebugMode then OutputDebugMode('FastMM5: FULL DEBUG MODE ENABLED');You will see this output in an app without EurekaLog, but not in app with EurekaLog.
That was exactly what customer did: he called the
FastMM_EnterDebugMode
function as first action in his project file (.dpr), but it is already too late: EurekaLog (as well as RTL and VCL) is already initialized at this point, so EurekaLog's memory filter is already set, therefore the FastMM_EnterDebugMode
function will do nothing.That was the reason: FastMM 5 did not detect anything, because FastMM's full debug mode was not enabled in the first place.
Is it possible to use FastMM 5 in full debug mode with EurekaLog?
Yes! All you need to do is to enable FastMM's full debug mode before EurekaLog sets its memory manager. In other words, the
FastMM_EnterDebugMode
function should be called before EMemLeaks
unit initializes. Order of initialization matters. You can do this in at least two different ways:- If you open the
FastMM5.pas
file, you would see documentation for FastMM. It mentions this among other things:The following conditional defines are supported:
which means you can add the
-
FastMM_FullDebugMode
(orFullDebugMode
) - If defined thenFastMM_EnterDebugMode
will be called on startup so that the memory manager starts in debug mode. IfFastMM_FullDebugMode
is defined andFastMM_DebugLibraryDynamicLoading
(orLoadDebugDLLDynamically
) is not defined thenFastMM_DebugLibraryStaticDependency
is implied.
-FastMM_FullDebugModeWhenDLLAvailable
(orFullDebugModeWhenDLLAvailable
) - If defined an attempt will be made to load the debug support library during startup. If successful thenFastMM_EnterDebugMode
will be called so that the memory manager starts up in debug mode.FastMM_FullDebugMode
(orFastMM_FullDebugModeWhenDLLAvailable
) conditional symbol to your project's options. You probably want to add it into your "Debug" build configuration only. Now, build your project, and it will have FastMM 5 in full debug mode for the "Debug" build configuration, but production version of FastMM 5 for the "Release" build configuration.
That way theFastMM_EnterDebugMode
function will be called when theFastMM5
unit is initialized - i.e. before theEMemLeaks
unit is initialized.
- Another way would be creating a
FastMM5_FDM.pas
unit like this:
unit FastMM5_FDM; interface implementation uses FastMM5; initialization FastMM_EnterDebugMode; end.
Place this unit as your first unit:
uses FastMM5_FDM, {$IFDEF EurekaLog} EMemLeaks, EResLeaks, // ...
That way theFastMM_EnterDebugMode
function will be called when theFastMM5_FDM
unit is initialized - i.e. before theEMemLeaks
unit is initialized.
FastMM_EnterDebugMode
function first, and then initialize EurekaLog's memory filter:
- The
FastMM_FullDebugMode
will enable full debug mode at design-time; - The
FastMM_FullDebugModeWhenDLLAvailable
will enable full debug mode depending if the debug support library is present; - The
FastMM5_FDM
unit will enable full debug mode at the run-time.