Reputation: 713
MadExcept says my app leaks "strings" memory on the following code:
for i := 0 to TotalSpans-1 do
begin
if i = 0 then LastPos := 1;
StartPos := PosEx(SubstrAtBegin, RawHtmlStr, LastPos);
FinishPos := PosEx(SubstrAtEnd, RawHtmlStr, LastPos);
Spans[i] := Copy(RawHtmlStr, StartPos, FinishPos - StartPos +
Length(SubstrAtEnd));
LastPos := FinishPos + Length(SubstrAtEnd);
end;
where Spans
is an array of string
.
The idea is to find the specific values in a long RawHtmlStr
. For that purpose I first locate the well-known adjacent substrings and then copy the value from between them to a dynamic array of strings.
The whole thing is serialized to work in threads.
On the last run I parsed about 15k of RawHtmlStr
s and there were 38 exceptions thrown (mostly EIdReadTimeout
and EIdSocketError
). I handled those exceptions on an upper lever (simply moving to the next item), but they somehow led to 34 UnicodeString
leaks.
madExcept points to the following line:
Spans[i] := Copy(RawHtmlStr, StartPos, FinishPos - StartPos +
Length(SubstrAtEnd));
as a source of evil.
At the moment the whole piece of code is NOT wrapped by try..finally
block because I do not quite understand how to handle the disposal of string array (which, I thought, is being taken care of by Delphi, no?).
Will Finalize(Spans)
do the garbage collection in this case?
Upvotes: 2
Views: 1375
Reputation: 613332
The object in question is of type
array of string
That is a dynamic array whose lifetime is managed by reference counting. The members of the array also have lifetime managed by reference count.
With managed objects you do not need to take any steps to dispose of them. At some point, when the final reference to the object leaves scope, the object is automatically destroyed.
So, if you are leaking such an object that would usually imply that whatever contains the object is not being destroyed. For example, this code would leak an array of strings:
type
TRec = record
arr: array of string;
end;
PRec = ^TRec;
....
var
Rec: PRec;
....
New(Rec);
SetLength(Rec.arr, 42);
Rec.arr[0] := 'foo';
// and so on
If you failed to dispose of Rec
then it, and its contents, would be leaked.
Likewise if you have a class that owns managed objects, and that class is leaked, then all the members of the class are also leaked.
type
TMyClass = class
arr: array of string;
end;
....
var
Obj: TMyClass;
....
Obj := TMyClass.Create;
SetLength(Obj.arr, 42);
Obj.arr[0] := 'foo';
// and so on
Again, if you fail to destroy Obj
, then it will leak, and so will its members.
Beyond that scenario, the only other way that I can imagine a managed type leaking is if a heap corruption overwrites the reference count.
Upvotes: 4