【发布时间】:2012-06-25 02:49:47
【问题描述】:
使用的版本: Delphi 7.
我正在开发一个在虚拟 ListView 上执行简单 for 循环的程序。数据存储在以下记录中:
type TList=record
Item:Integer;
SubItem1:String;
SubItem2:String;
end;
Item 是索引。 SubItem1 操作的状态(成功与否)。 SubItem2 文件的路径。 for 循环加载每个文件,执行一些操作,然后保存它。操作发生在 TStringList 中。每个文件大约 2mb。
现在,如果我在主窗体上进行操作,它可以完美运行。
多线程,存在巨大的内存问题。不知何故, TStringList 似乎没有被完全释放。在 3-4k 个文件之后,我得到一个 EOutofMemory 异常。有时,软件卡在 500-600mb,有时则没有。在任何情况下,TStringList 总是返回一个 EOutofMemory 异常并且不能再加载任何文件。在内存更大的计算机上,获取异常需要更长的时间。
同样的事情发生在其他组件上。例如,如果我使用 Synapse 的 THTTPSend,那么,一段时间后,软件无法创建任何新线程,因为内存消耗太高。它大约是 500-600mb,而最大应该是 100mb。在主窗体上,一切正常。
我想错误是在我这边。也许我对线程的了解不够。我试图释放 Destroy 事件中的所有内容。我尝试了 FreeAndNil 程序。我一次只尝试一个线程。我尝试手动释放线程(没有 FreeOnTerminate...)
运气不好。
所以这里是线程代码。这只是基本的想法;不是所有操作的完整代码。如果我删除 LoadFile 程序,一切正常。根据线程池为每个文件创建一个线程。
unit OperationsFiles;
interface
uses Classes, SysUtils, Windows;
type
TOperationFile = class(TThread)
private
Position : Integer;
TPath, StatusMessage: String;
FileStringList: TStringList;
procedure UpdateStatus;
procedure LoadFile;
protected
procedure Execute; override;
public
constructor Create(Path: String; LNumber: Integer);
end;
implementation
uses Form1;
procedure TOperationFile.LoadFile;
begin
try
FileStringList.LoadFromFile(TPath);
// Operations...
StatusMessage := 'Success';
except
on E : Exception do StatusMessage := E.ClassName;
end;
end;
constructor TOperationFile.Create(Path : String; LNumber: Integer);
begin
inherited Create(False);
TPath := Path;
Position := LNumber;
FreeOnTerminate := True;
end;
procedure TOperationFile.UpdateStatus;
begin
FileList[Position].SubItem1 := StatusMessage;
Form1.ListView4.UpdateItems(Position,Position);
end;
procedure TOperationFile.Execute;
begin
FileStringList:= TStringList.Create;
LoadFile;
Synchronize(UpdateStatus);
FileStringList.Free;
end;
end.
可能是什么问题?
我曾一度认为,可能创建了太多线程。如果用户加载 100 万个文件,那么最终将创建 100 万个线程——尽管只有 50 个线程同时被创建和运行。
感谢您的意见。
【问题讨论】:
-
@TLama 已经这样做了……根据 FastMM 的说法,除了 Delphi 7 中的内存泄漏之外,没有内存泄漏。
-
@TLama 13 - 20 字节:AnsiString x 1 29 - 36 字节:未知 x 1 45 - 52 字节:TStringList x 2 我相信这些是 Delphi 本身的内存泄漏。如果我错了,请纠正我。
-
我从来没有经历过 Delphi 本身的任何内存泄漏。
-
Fastmm 可以提供泄漏内存分配的调用堆栈,请确保您安装了完整版本的 Fastmm。除此之外,您没有显示
FileList的填充方式。我怀疑你的线程代码抛出了一个你不处理的异常,绕过了你对TStringList.Free()的调用。添加try/finally块,或覆盖DoTerminate(),以确保始终调用Free()。 -
@Jerry 旧版 Delphis 中的 RTL/VCL 泄露。 Emba 在开始使用 FastMM 时就开始修复这些漏洞。
标签: delphi memory ram tstringlist tthread