I have a lot of memory allocations and the same number of FreeMem calls. What I didn't have though is a check before calling freemem to see if the pointer was nil, and a line after freeing to set the pointer to nil.
I tried to create a function to do this
procedure FreeMemAndNil(p: Pointer; size: Integer = -1);
begin
if p <> nil then
begin
if size > -1 then
FreeMem(p, size)
else
FreeMem(p);
p := nil;
end;
end;
But there's a problem. It can't set the origional pointer to nil because the parameter isn't variable (var p: Pointer). I can't use var though because if I do the compiler complains the type has to be the exact same type (Pointer). The pointers I'm passing could be pointers to any type (PChar, regular pointer, etc.).
What can I do to fix this? Is there a better solution?
Like Mason Wheeler said you should use the same trick as FreeAndNil in the SysUtils unit does on object references.
So I modified your code, unit tested it, and this works fine:
procedure FreeMemAndNil(var ptr; size: Integer = -1);
var
p: Pointer;
begin
p := Pointer(ptr);
if p <> nil then
begin
if size > -1 then
FreeMem(p, size)
else
FreeMem(p);
Pointer(ptr) := nil;
end;
end;
--jeroen
PS: Rob Kennedy wrote a nice answer on untyped var parameters that has a link to his untyped parameter page on the internet.
PS2: For reference: The Kylix version of SysUtils.pas is on-line, and the FreeAndNil there is identical to how it is in Delphi.