Memory Safety and Delphi in the news

FastMM does some of those things, but others are very hard indeed for a memory manager to do. Or impossible.

I believe that some of them work as follows (I’d have to check my old article on CodeGuard to see if I knew how they worked back then - my memory manager deallocated that knowledge years ago :smile:):

  • Access in freed memory: when a block is freed the mm overwrites the block with a pattern and delays actually releasing the memory for a while. Later, when it is time to release the memory it checks that the pattern is still intact and actually releases the memory. If the pattern was modified then an invalid write occurred. This doesn’t catch read access though. This technique detects write access to freed memory if it would have otherwise been reallocated for another purpose
  • Method called on freed object: Hook all class member functions. When the hook function is called check the implicit Self parameter against valid memory blocks and call the original function
  • Access overrun (also available in FastMM) and underrun: Add some guard memory to the start and end of each allocated block and fill with a pattern. When the object is freed check that the patterns are still intact. Again, won’t catch an invalid read
  • Access uninitialized/invalid stack: Function hooks, check stack pointer and frame have just been initialized, maybe push a pattern on the stack, call the original function, maybe check pattern on return

To help catch access in freed memory immediately, at least where the memory is not reallocated, and to catch reads, you could use something to trigger AV’s like the following instead of calling .Free:

procedure FreeAndInvalidate(var Obj);
var
  Temp: TObject;
begin
  Temp := TObject(Obj);
  Pointer(Obj) := $C0FFEE;
  Temp.Free;
end;

  var o := TThing.Create;
  ...
  FreeAndInvalidate(o);
  ...
  // Access member field or call a method that does = AV: read of address 00C0FFEE
  if o.Something = 42 then ...

Calling FreeAndNil() also works but that would get mixed in with ‘access before allocated’ or other uninitialised ref code.

1 Like