Closed D3lphi3r closed 6 years ago
This is normal and intentional behavior.
Look at the initialization
and finalization
sections of the IdThread.pas
unit:
initialization
...
GThreadCount := TIdThreadSafeInteger.Create;
{$IFNDEF FREE_ON_FINAL}
{$IFDEF REGISTER_EXPECTED_MEMORY_LEAK}
IndyRegisterExpectedMemoryLeak(GThreadCount);
IndyRegisterExpectedMemoryLeak(TIdThreadSafeIntegerAccess(GThreadCount).FCriticalSection);
{$ENDIF}
{$ENDIF}
finalization
...
{$IFDEF FREE_ON_FINAL}
//only enable this if you know your code exits thread-clean
FreeAndNil(GThreadCount);
{$ENDIF}
end.
As well as in the IdStack.pas
unit, too:
initialization
...
GStackCriticalSection := TIdCriticalSection.Create;
{$IFNDEF DOTNET}
{$IFDEF REGISTER_EXPECTED_MEMORY_LEAK}
IndyRegisterExpectedMemoryLeak(GStackCriticalSection);
{$ENDIF}
{$ENDIF}
finalization
// Dont Free. If shutdown is from another Init section, it can cause GPF when stack
// tries to access it. App will kill it off anyways, so just let it leak
{$IFDEF FREE_ON_FINAL}
FreeAndNil(GStackCriticalSection);
{$ENDIF}
end.
As you can see, there are a few global objects being intentionally leaked when FREE_ON_FINAL
is not defined (which it is not by default, see IdCompilerDefines.inc
).
See Why does FREE_ON_FINAL exists? for more details.
On systems where the memory manager supports registering known leaks, they are registered by default so that they DO NOT appear in leak reports:
{$IFDEF VCL_2006_OR_ABOVE}
...
{$DEFINE HAS_System_RegisterExpectedMemoryLeak}
{$IFNDEF FREE_ON_FINAL}
{$IFNDEF DOTNET}
{$DEFINE REGISTER_EXPECTED_MEMORY_LEAK}
{$ENDIF}
{$ENDIF}
...
{$ENDIF}
...
{$IFNDEF FREE_ON_FINAL}
{$IFNDEF REGISTER_EXPECTED_MEMORY_LEAK}
{$IFDEF USE_FASTMM4}
{$DEFINE REGISTER_EXPECTED_MEMORY_LEAK}
{$ENDIF}
{$IFDEF USE_MADEXCEPT}
{$DEFINE REGISTER_EXPECTED_MEMORY_LEAK}
{$ENDIF}
{$IFDEF USE_LEAKCHECK}
{$DEFINE REGISTER_EXPECTED_MEMORY_LEAK}
{$ENDIF}
{$ENDIF}
{$ENDIF}
{$IFDEF REGISTER_EXPECTED_MEMORY_LEAK}
{$IFDEF DOTNET}
{$UNDEF REGISTER_EXPECTED_MEMORY_LEAK}
{$ENDIF}
{$IFDEF VCL_CROSS_COMPILE}
// RLebeau: this should be enabled for Windows, at least...
{$IFNDEF MSWINDOWS}
// RLebeau: LeakCheck has leak reporting on other platforms...
{$IFNDEF USE_LEAKCHECK}
{$UNDEF REGISTER_EXPECTED_MEMORY_LEAK}
{$ENDIF}
{$ENDIF}
{$ENDIF}
{$ENDIF}
When REGISTER_EXPECTED_MEMORY_LEAK
is defined, the IdGlobal.pas
unit implements a public IndyRegisterExpectedMemoryLeak()
function to call the appropriate registration function:
{$IFNDEF DOTNET}
{$IFDEF REGISTER_EXPECTED_MEMORY_LEAK}
function IndyRegisterExpectedMemoryLeak(AAddress: Pointer): Boolean;
{$IFDEF USE_INLINE}inline;{$ENDIF}
begin
// use only System.RegisterExpectedMemoryLeak() on systems that support
// it. We should use whatever the RTL's active memory manager is. The user
// can override the RTL's version of FastMM (2006+ only) with any memory
// manager they want, such as MadExcept.
//
// Fallback to specific memory managers if System.RegisterExpectedMemoryLeak()
// is not available.
{$IFDEF HAS_System_RegisterExpectedMemoryLeak}
// RLebeau 4/21/08: not quite sure what the difference is between the
// SysRegisterExpectedMemoryLeak() and RegisterExpectedMemoryLeak()
// functions in the System unit, but calling RegisterExpectedMemoryLeak()
// is causing stack overflows when FastMM is not active, so call
// SysRegisterExpectedMemoryLeak() instead...
// RLebeau 7/4/09: According to Pierre Le Riche, developer of FastMM:
//
// "SysRegisterExpectedMemoryLeak() is the leak registration routine for
// the built-in memory manager. FastMM.RegisterExpectedMemoryLeak is the
// leak registration code for FastMM. Both of these are thus hardwired to
// a specific memory manager. In order to register a leak for the
// *currently installed* memory manager, which is what you typically want
// to do, you have to call System.RegisterExpectedMemoryLeak().
// System.RegisterExpectedMemoryLeak() redirects to the leak registration
// code of the installed memory manager."
//Result := System.SysRegisterExpectedMemoryLeak(AAddress);
Result := System.RegisterExpectedMemoryLeak(AAddress);
{$ELSE}
// RLebeau 10/5/2014: the user can override the RTL's version of FastMM
// (2006+ only) with any memory manager, such as MadExcept, so check for
// that...
{$IFDEF USE_FASTMM4}
Result := FastMM4.RegisterExpectedMemoryLeak(AAddress);
{$ELSE}
{$IFDEF USE_MADEXCEPT}
Result := madExcept.HideLeak(AAddress);
{$ELSE}
{$IFDEF USE_LEAKCHECK}
Result := LeakCheck.RegisterExpectedMemoryLeak(AAddress);
{$ELSE}
Result := False;
{$ENDIF}
{$ENDIF}
{$ENDIF}
{$ENDIF}
end;
{$ENDIF}
{$ENDIF}
As you can see above, IndyRegisterExpectedMemoryLeak()
is being called for the leaked objects when possible.
However, all of the above applies to Delphi only, because FreePascal's heaptrc
DOES NOT support registering known leaks!
It's all clear now.
The following code reported memory leak
Below is the trace log