Home > Blockchain >  When is it safe to Dispose a nil pointer?
When is it safe to Dispose a nil pointer?

Time:01-24

In the following example:

program DisposeProblem;

{$APPTYPE CONSOLE}

{$R *.res}

uses
  System.SysUtils;

type
  Person = record
    name: string;
    age: Integer;
  end;

var
  p: ^Person;

begin
  p := nil;
  Dispose(nil); // OK
  Dispose(p); // AV
end.

Why is the first Dispose() call OK, while the second causes an access violation error? When I step through the code, the first Dispose() calls System._FreeMem(), while the second calls System._Dispose(), but I don't understand why this is the case. I would like to understand this behavior so I can know when it is safe to call Dispose() on a nil pointer.

CodePudding user response:

I would like to understand this behavior so I can know when it is safe to call Dispose() on a nil pointer.

It is never OK to call Dispose() on a nil pointer variable. The RTL expects the variable to point at valid memory allocated with New(), and so will unconditionally try to finalize whatever data/object is being pointed at. Passing in a pointer variable that is nil leads to undefined behavior and will likely crash.

Dispose(nil) is effectively a no-op. The compiler knows the nil literal can't possibly point at a data type that needs to be finalized, so it doesn't need to call System._Dispose(), hence it calls System._FreeMem() instead (why it calls anything at all, I don't know).

System._FreeMem() allows nil as input, it will simply exit without doing anything. However, System._Dispose() on a pointer variable does not allow nil as input (and never has).

  • Related