In my last article “Jwscl and FreeAndNil” there were some great comments on the source design. Oliver told me to use a guarded memory page so the memory is always invalid. With his information I wrote a source code that creates a pointer which always triggers an access violation.

Unfortunately, Access Violations are rather common and thus nobody can tell why it happens at a first glance. So I added an exception handler that maps this special access violation to a separate exception class (I called it EJwsclAccessedGuardPointerException).

uses
  ExceptionLog,
  //JwaWindows, //or
  JwaWinBase, JwaWinNT, JwaNtStatus,
  SysUtils;

type
  EJwsclAccessedGuardPointerException = class(Exception)
  public
    ExceptionRecord: PExceptionRecord;
  end;

resourcestring
  SGuardPageException = 'It was tried to access a guarded pointer. This '+
   'pointer was freed previously and is now accessed without initialization. '+
   'JWSCL may guard its class members in this way. You should check for '+
   ' accesses to e.g. class members which instance was freed.'#13#10+
   'Exception was raised at this address: $%p';

var
  GuardPtr : Pointer;
  OldExcpObj : function (P: PExceptionRecord): Exception;
  OldExitProc : procedure;

procedure MyExitProcessProc;
begin
  VirtualFree(GuardPtr, 0, MEM_RELEASE);

  if @OldExitProc <> nil then
    OldExitProc;
end;

function MyGetExceptionObject(P: PExceptionRecord): Exception;
var ErrorCode : Integer;
begin
  if (P.ExceptionCode = STATUS_ACCESS_VIOLATION) and
    (P.ExceptObject = GuardPtr) then
  begin
    result := EJwsclAccessedGuardPointerException.CreateFmt(SGuardPageException,
        [P.ExceptionAddress]);
    EJwsclAccessedGuardPointerException(Result).ExceptionRecord := P;
  end
  else
  begin
    result := OldExcpObj(P);
  end;
end;

var
  T : TObject;
  SysInfo : TSystemInfo;
begin
  OldExcpObj := ExceptObjProc;
  ExceptObjProc := @MyGetExceptionObject;

  OldExitProc := ExitProcessProc;
  ExitProcessProc := MyExitProcessProc;

  //On 32Bit OS call
  //GetSystemInfo(@SysInfo);
  //On WOW64Bit OS call (use IsWow64Process)
  GetNativeSystemInfo(@SysInfo);

  GuardPtr := VirtualAlloc(
    Pointer($BADC0DE),//  __in_opt  LPVOID lpAddress,
    SysInfo.dwPageSize,//  __in      SIZE_T dwSize,
    MEM_RESERVE,//  __in      DWORD flAllocationType,
    PAGE_NOACCESS//  __in      DWORD flProtect
  );
  if GuardPtr = nil then
    RaiseLastOSError;

  T := TObject(Pointer(GuardPtr));
  T.Free;
end.

Since the object has this guard pointer value (which may be dynamic) a call to Free (or Destroy) will fail with the exception EJwsclAccessedGuardPointerException. Be aware that there is no actual memory allocated. It is all about virtual memory.

The MyExitProcessProc is called right before the process exits. There is another exit handler called ExitProc that is called before the units are finalized. So I’m stuck with ExitProcessProc which is fine though.

I must say that I like this approach since it seems to be safer than just using a nearly arbitrary magic value. The value is still there so you can see it as an invalid memory address in a debugger. However, Assigned or similar workarounds will not work because the memory location can vary.
And of course the exception message clearly states what happened here.  There could added more information like stack trace but that I leave to you (or the JCL).

Be aware that there still might be errors. This code is hot.  8-)

What is your opinion?