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
是一个字符串数组
。
其想法是在长 RawHtmlStr
中查找特定值。为此,我首先找到众所周知的相邻子字符串,然后将它们之间的值复制到动态字符串数组中。
整个事情被序列化以在线程中工作。
在最后一次运行中,我解析了大约 15k 个 RawHtmlStr
,并且抛出了 38 个异常(主要是 EIdReadTimeout
) > 和 EIdSocketError
)。我在上层处理了这些异常(只需移至下一个项目),但它们以某种方式导致了 34 个 UnicodeString
泄漏。
madExcept 指向以下行:
Spans[i] := Copy(RawHtmlStr, StartPos, FinishPos - StartPos +
Length(SubstrAtEnd));
作为邪恶之源。
目前整段代码没有被 try..finally
block 包装,因为我不太明白如何处理字符串数组的处理(我认为,它正在被采取)由德尔福照顾,不是吗?)。
在这种情况下,Finalize(Spans)
会执行垃圾回收吗?
最佳答案
有问题的对象是类型
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
,那么它就会泄漏,它的成员也会泄漏。
除了这种情况之外,我可以想象托管类型泄漏的唯一其他方式是堆损坏覆盖引用计数。
关于delphi - 如何正确处理字符串数组以防止内存泄漏?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/23237970/