程序提交太多内存

时间:2011-11-07 14:54:17

标签: delphi memory

  

可能重复:
  TStringList of objects taking up tons of memory in Delphi XE

我有一个程序需要一段时间才能运行并使用相当大的内存(大约800 MB开始,大约1.1 GB)。

我遇到的问题是,即使它使用的内存量很少,提交的内存量也会超过4GB并且会给我一个“内存不足”的信息。错误。

以下是资源监视器的屏幕截图:

A screen shot of Resource Monitor

占用内存的主要内容是一个TStringList,它填充了一个具有一堆不同值和一些字符串列表的对象

有谁知道为什么它提交的内存比我需要的多得多,我怎么能让我的程序不这样做呢?

4 个答案:

答案 0 :(得分:1)

提交大小是程序分配的内存量(但不一定在物理内存中)。正如评论中所提到的,程序很可能存在内存泄漏(例如,它可能会创建对象但不会删除它们)。因此,即使使用的内存量是“合理的”,它也不一定代表实际分配​​的数量,并且32位系统中的数量不能“通常”超过4GB。 This question讨论了可能有用的泄漏检测工具。

答案 1 :(得分:1)

您的软件可能包含内存泄漏。将这小段代码放在程序的“主”块之后(.dpr文件 - 按F7到达那里)。

   {$WARN SYMBOL_PLATFORM OFF}
   ReportMemoryLeaksOnShutdown := DebugHook <> 0;

因此,最终结果应与此类似:

 begin
  {$WARN SYMBOL_PLATFORM OFF}
  ReportMemoryLeaksOnShutdown := DebugHook <> 0;

  Application.Initialize;
  Application.CreateForm(TForm1, Form1);
  Application.Run;
 end.

然后,运行您的程序,直到您获得一些大的内存使用并简单地退出它。 Delphi将显示一个漂亮的窗口,为您提供内存泄漏的大小以及有关它们可能发生的位置的一些提示。

祝你好运!

答案 2 :(得分:0)

您没有显示代码,但此效果似乎是内存泄漏的结果 所以,这个TStringList(我称之为 parent )有关联的对象,它们有自己的子TStringLists(我想它只有字符串)。

执行此内存管理的更简单方法是让TStringList为您执行此操作:

  • 如果在Delphi版本中您有TStringList具有 OwnsObjects 属性,请将其设置为 true 。这样,每次调用删除清除方法都会调用与列表关联的对象的析构函数 - 这样即使cll 父母。弗里。如果它没有实现,你必须自己做 - 在后代类中覆盖TStringList的Delete,Clear和Destroy方法。
  • 确保子对象的析构函数正确清理在其中创建的对象 - 如果子对象中的一个字符串列表拥有对象,则可以在上面的项目中使用相同的策略。

(简化)示例:

TMyChildObject = class
private
  fMyListOfMagazineNames, 
  // This one will have TBitmap instances associated with the dogs names
  fMyListOfDogNamesAndPhotos : TStringList;
  fName: String;
public 
  //[properties, methods, whatever]

  property Name: string read fName write fName;
  constructor Create; virtual;
  destructor Destroy; override;
end;

constructor TMyChildObject.Create;
begin
  inherited Create;
  fMyListOfMagazineNames = TStringList.Create;
  fMyListOfDogNamesAndPhotos = TStringList.Create; 
  fMyListOfDogNamesAndPhotos.OwnsObjects := True;
end;

destructor TMyChildObject.Destroy;
begin
  fMyListOfMagazineNames.Free;
  fMyListOfDogNamesAndPhotos.Free;
  inherited Destroy;
end;

使用示例:

var 
  MyObjList: TStringList;
begin
  MyObjList := TStringList.Create;
  MyObjList.OwnsObjects := True;

  // Create your child objects

  // And Free them at once 
  MyObjList.Free;
end;

答案 3 :(得分:0)

正如您previous question中所述 - 感谢您选择了一个答案。

问题的主要解决方案是来分配内存中的所有对象。如果您的28 MB初始数据占用的内存超过1 GB,则会有大量冗余信息。

您应该修改算法:

  • 使用SQL数据库来处理您的数据而不会出现内存问题(使用正确的索引) - 可能是SQLite3或嵌入式Firebird可以很好地工作;
  • 将数据保留在输入文件中,内存映射它们而不是在内存中分配副本:对每个属性使用getter方法,以便即时检索值;
  • 使用NoSQL数据库(如this),它可能比SQL数据库更快地插入行,并消耗更少的磁盘空间和内存;
  • 或者......考虑压缩对象内容(fast compression是个不错的选择。)