Skip to content

Commit

Permalink
Added some "address space slack" under FullDebugMode. This reserves a…
Browse files Browse the repository at this point in the history
… block of address space on startup (currently 5MB) that is released just before the first time an EOutOfMemory exception is raised, allowing some GetMem calls following the initial EOutOfMemory to succeed. This allows the application to perform any error logging and other shutdown operations successfully that would have failed if the address space was actually completely exhausted. (Under FullDebugMode address space is never released back to the operating system so once the address space has been exhausted there is very little room to manoeuvre.)
  • Loading branch information
Pierre le Riche committed Jan 22, 2018
1 parent 4172398 commit e7ab784
Showing 1 changed file with 37 additions and 1 deletion.
38 changes: 37 additions & 1 deletion FastMM4.pas
Original file line number Diff line number Diff line change
Expand Up @@ -849,7 +849,16 @@
immediately during a FreeMem call the block will added to a list of blocks
that will be freed later, either in the background cleanup thread or during
the next call to FreeMem.
Version 4.??? (unreleased)
- Added some "address space slack" under FullDebugMode. This reserves a
block of address space on startup (currently 5MB) that is released just
before the first time an EOutOfMemory exception is raised, allowing some
GetMem calls following the initial EOutOfMemory to succeed. This allows
the application to perform any error logging and other shutdown operations
successfully that would have failed it the address space was actually
completely exhausted. (Under FullDebugMode address space is never released
back to the operating system so once the address space has been exhausted
there is very little room to manoeuvre.)
*)

unit FastMM4;
Expand Down Expand Up @@ -1461,6 +1470,11 @@ procedure LogReleaseStackUsage;
{$else}
DebugFillPattern = $8080808080808080;
{$endif}
{The number of bytes of address space that cannot be allocated under FullDebugMode. This block is reserved on
startup and freed the first time the system runs out of address space. This allows some subsequent memory allocation
requests to succeed in order to allow the application to allocate some memory for error handling, etc. in response to
the first EOutOfMemory exception.}
FullDebugModeAddressSpaceSlack = 5 * 1024 * 1024;

{-------------------------FullDebugMode structures--------------------}
type
Expand Down Expand Up @@ -2128,6 +2142,10 @@ TExpectedMemoryLeaks = record
{The 64K block of reserved memory used to trap invalid memory accesses using
fields in a freed object.}
ReservedBlock: Pointer;
{Points to a block of size FullDebugModeAddressSpaceSlack that is freed the first time the system runs out of memory.
Memory is never release under FullDebugMode, so this allows the application to continue to function for a short while
after the first EOutOfMemory exception.}
AddressSpaceSlackPtr: Pointer;
{The virtual method index count - used to get the virtual method index for a
virtual method call on a freed object.}
VMIndex: Integer;
Expand Down Expand Up @@ -9652,6 +9670,16 @@ function DebugGetMem(ASize: {$ifdef XE2AndUp}NativeInt{$else}Integer{$endif}): P
{$endif LogLockContention}
Result := nil;
end;
end
else
begin
{The process ran out of address space: Release the address space slack so that some subsequent GetMem calls will
succeed in order for any error logging, etc. to complete successfully.}
if AddressSpaceSlackPtr <> nil then
begin
VirtualFree(AddressSpaceSlackPtr, 0, MEM_RELEASE);
AddressSpaceSlackPtr := nil;
end;
end;
finally
{Leaving the memory manager routine: Block scans may be performed again.}
Expand Down Expand Up @@ -12601,6 +12629,8 @@ procedure InstallMemoryManager;
{$ifdef 32Bit}
{Try to reserve the 64K block covering address $80808080}
ReservedBlock := VirtualAlloc(Pointer(DebugReservedAddress), 65536, MEM_RESERVE, PAGE_NOACCESS);
{Allocate the address space slack.}
AddressSpaceSlackPtr := VirtualAlloc(nil, FullDebugModeAddressSpaceSlack, MEM_RESERVE or MEM_TOP_DOWN, PAGE_NOACCESS);
{$endif}
{$endif}
{$ifdef MMSharingEnabled}
Expand Down Expand Up @@ -12803,6 +12833,12 @@ procedure UninstallMemoryManager;
VirtualFree(ReservedBlock, 0, MEM_RELEASE);
ReservedBlock := nil;
end;
{Release the address space slack}
if AddressSpaceSlackPtr <> nil then
begin
VirtualFree(AddressSpaceSlackPtr, 0, MEM_RELEASE);
AddressSpaceSlackPtr := nil;
end;
{$endif}
end;
{$ifndef DetectMMOperationsAfterUninstall}
Expand Down

0 comments on commit e7ab784

Please sign in to comment.