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?