[DUG] Dumb Friday Question
Judd, Struan (eCargo)
struan.judd at ecargo.co.nz
Fri May 4 13:45:34 NZST 2007
Jeremy Coulter wrote:
> Hi All. This is a question that might be infulenced by some serious
> lack of sleep :-)
>
> I have a funtion. Its return result is a TStringlist.
> In my code I create a TStringlist then add my values to it, then pass
> this to the RESULT varaible for the function.
>
> Now, this is prob. an obvious answer than I prob. do actually know,
> but if I got:-
>
> sResult := TStringList.create;
> sResult.add('blah');
> Result:=sResult;
>
> Then if I free sResult, then I loss the values I added, and the
> result is empty as you would expect.
> But the issue I have is, so if I DONT free sResults, what happens to
> it? Surley it stays in memory,a dn I would end up with a memory leack
> after repeaditive calls. Is that right? Or is because the variable is
> function specific its free by default etc? Its a basic question I
> know....but the more I thought about it the more uncertain I
> became....I really need some sleep so that prob. the real probelm :-)
>
> Jeremy
You first answer is right, you get a new object each call and if you
don't free it outside of the function you will get a gradual memory
leak.
The real kicker with this style of function is that you can get an
uncool memory leak in the following circumstances.
First some code that works fine. It creates and cleans up after itself
properly.
----
Function GetAStringList: TStringList;
Var
tmpStringList: TStringList;
Begin
tmpStringList := TStringList.Create;
tmpStringList.Add('Hello');
tmpStringList.Add('World');
Result := tmpStringList;
End;
Procedure UseAStringList;
Var
aStringList: TStringList;
Begin
aStringList := GetAStringList;
try
WriteLn(aStringList.Text);
finally
aStringList.Free;
end;
End;
----
But if GetAStringList throws an exception after creating the StringList
but before returning it then you get a memory leak. Obvious right.
Result never get set so the value to Free never gets passed back to
UseAStringList
----
Function GetAStringList: TStringList;
Var
tmpStringList: TStringList;
Begin
tmpStringList := TStringList.Create;
tmpStringList.Add('Hello');
raise Exception.Create('World');
Result := tmpStringList;
End;
----
Now the real kicker is if you code using the Result pseudo-variable
instead then you still get a memory leak.
----
Function GetAStringList: TStringList;
Begin
Result := TStringList.Create;
Result.Add('Hello');
raise Exception.Create('World');
End;
----
This is because the function never *returns* properly and so even though
the Result pseudo-variable gets the address of the new TStringList, this
value is never pased back into the aStringList variable and thus the
Free method has nothing to work on.
This little quirk took a day or two to figure out a while back and had
the result that I ALWAYS wrap subsequent code in a creation function in
a try except block like follows.
----
Function GetAStringList: TStringList;
Begin
Result := TStringList.Create;
try
Result.Add('Hello');
raise Exception.Create('World');
except
Result.Free;
raise;
end;
End;
----
If an exception is raised in the Constructor, Delphi promises that it'll
Free the partially created object, but once the object gets into your
code it's your responsibility to free it. :)
Of course, none of the above applies to Delphi.Net code.
TTFN, Struan Judd.
DISCLAIMER: This electronic message together with any attachments is
confidential. If you are not the intended recipient, do not copy, disclose or
use the contents in any way. Please also advise us by return e-mail that you
have received the message and then please destroy. Carter Holt Harvey is not
responsible for any changes made to this message and / or any attachments after
sending by Carter Holt Harvey. We use virus scanning software but exclude all
liability for viruses or anything similar in this email or any attachment.
More information about the Delphi
mailing list