MadExcept说我的应用程序漏了"字符串"以下代码中的内存:
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;
其中Spans
是array of string
。
想法是在长RawHtmlStr
中找到具体的值。为此,我首先找到众所周知的相邻子串,然后将它们之间的值复制到动态字符串数组中。
整个事情被序列化以在线程中工作。
在最后一次运行中,我解析了大约15k的RawHtmlStr
s并且抛出了38个异常(主要是EIdReadTimeout
和{{1} })。我在上部杠杆上处理了这些例外(只是移动到下一个项目),但它们以某种方式导致34 EIdSocketError
泄漏。
madExcept指向以下行:
UnicodeString
作为邪恶的来源。
目前整段代码没有被Spans[i] := Copy(RawHtmlStr, StartPos, FinishPos - StartPos +
Length(SubstrAtEnd));
块包裹,因为我不太明白如何处理字符串数组(我认为,这是由Delphi处理的,没有?)。
在这种情况下,try..finally
会进行垃圾收集吗?
答案 0 :(得分:4)
有问题的对象是
类型array of string
这是一个动态数组,其生命周期由引用计数管理。阵列的成员也有通过引用计数管理的生命周期。
使用托管对象,您无需采取任何步骤来处置它们。在某些时候,当对象的最终引用离开作用域时,对象会自动销毁。
所以,如果你正在泄漏这样一个通常意味着包含该对象的东西没有被破坏的对象。例如,此代码会泄漏字符串数组:
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
如果您没有处置Rec
,那么它及其内容将被泄露。
同样,如果你有一个拥有托管对象的类,并且该类被泄露,那么该类的所有成员也会泄露。
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
同样,如果你没有销毁Obj
,那么它就会泄漏,其成员也会泄漏。
除了这种情况之外,我可以想象托管类型泄漏的另一种方式是堆损坏会覆盖引用计数。