Using just FillChar
is wrong here. If any of the WideString
members are not empty, then you will leak them this way. Instead I suggest the following:
Finalize(IPInfo);
FillChar(IPInfo, SizeOf(TIPInfo), 0);
Or another way is to define a default record as a typed constant:
const
DefaultIPInfo: TIPInfo = ();
Then you can use simple assignment:
IPInfo := DefaultIPInfo;
In modern versions of Delphi you can instead use this much more readable code:
IPInfo := Default(TIPInfo);
For more on this particular subject, refer to these topics:
Note that the leak in your code is hard to find because WideString
variables are implemented as COM BSTR
objects, and allocated on the COM heap. Therefore, if you use memory leak detection for the Delphi memory manager the leak will not be detected because it is leaked from a different heap.
In your case, because your record is a managed type, and contains only managed types, then you could use an out
parameter to good effect. For managed types, out
parameters mean that the compiler will generate code, at the call site, to default initialize the record before passing it in.
Consider the following program:
{$APPTYPE CONSOLE}
type
TRec = record
Value: WideString;
end;
procedure Foo1(var rec: TRec);
begin
end;
procedure Foo2(out rec: TRec);
begin
end;
procedure Main;
var
rec: TRec;
begin
rec.Value := 'Foo';
Foo1(rec);
Writeln(rec.Value);
Foo2(rec);
Writeln(rec.Value);
end;
begin
Main;
end.
The output is:
Foo
If your record contains a mix of managed and unmanaged types, then the situation is not so good.
{$APPTYPE CONSOLE}
type
TRec = record
Value1: WideString;
Value2: Integer;
end;
procedure Foo1(var rec: TRec);
begin
end;
procedure Foo2(out rec: TRec);
begin
end;
procedure Main;
var
rec: TRec;
begin
rec.Value1 := 'Foo';
rec.Value2 := 42;
Foo1(rec);
Writeln(rec.Value1);
Writeln(rec.Value2);
Foo2(rec);
Writeln(rec.Value1);
Writeln(rec.Value2);
end;
begin
Main;
end.
The output is:
Foo
42
42
Only the managed members are default initialized for out
parameters. So your best bet is to default initializing the variable yourself, even if it is passed as an out
parameter.
More on out
parameters can be found here: What's the difference between "var" and "out" parameters?