德尔福:如何发现和修复的EOutOfMemory错误?(Delphi: How to find an

2019-09-16 08:50发布

我建立一个Delphi应用程序,它确实科学模拟。 它的增长的复杂性和目前由许多单位和形式。

我开始我每次运行时得到EOutOFMemory错误。 这似乎发生过程中或就在我使用的变体数组暂时内的功能。 在问一个非常愚蠢的问题的风险,是“变型阵列”引狼入室? (我可以一切转换成字符串,但原则上变型的阵列节省了大量的捏造的东西)。

违规阵列中使用可能是:

 Function  TProject.GetCurrentProjParamsAsArray(LProjectName, LProjectType : ShortString): ArrayOfVariant;
Var
  ArrayIndex : Word;
begin
    SetLength (Result,54);
    ArrayIndex := 0;
    Result [ArrayIndex] := LProjectName;        Inc(ArrayIndex);
    Result [ArrayIndex] := LProjectType;        Inc(ArrayIndex);                   // this structure makes it easier to add extra fields in the DB than hard coding the array index!!
    Result [ArrayIndex] := FileTool.DateTimeForFileNames    ;    Inc(ArrayIndex);
    Result [ArrayIndex] := SiteAndMet.  SiteName            ;    Inc(ArrayIndex);
    Result [ArrayIndex] := SiteAndMet.  PostCode            ;    Inc(ArrayIndex);
    Result [ArrayIndex] := SiteAndMet.  MetFileNamePath     ;    Inc(ArrayIndex);
    Result [ArrayIndex] := SiteAndMet.  SiteLat             ;    Inc(ArrayIndex);
    Result [ArrayIndex] := SiteAndMet.  SiteLong            ;    Inc(ArrayIndex);
    Result [ArrayIndex] := SiteAndMet.  SiteAlt             ;    Inc(ArrayIndex);
    Result [ArrayIndex] := SiteAndMet.  TZoneIndex          ;    Inc(ArrayIndex);
    Result [ArrayIndex] := SiteAndMet.  TZoneHours          ;    Inc(ArrayIndex);
    Result [ArrayIndex] := SiteAndMet.  TZoneMeridian       ;    Inc(ArrayIndex);
    Result [ArrayIndex] := SiteAndMet.  Albedo              ;    Inc(ArrayIndex);
    Result [ArrayIndex] := SiteAndMet.  ArrayTilt           ;    Inc(ArrayIndex);
    Result [ArrayIndex] := SiteAndMet.  ArrayAzimuth        ;    Inc(ArrayIndex);

在任务管理器 - 峰值内存使用量是42MB,VM是31M和我得到每轮〜90000个错误。 (XP的机器与3GB RAM上)

有没有人对我的应用程序中的不同组件监控内存使用任何通用的技巧? 或者在跟踪这个错误的原因是什么?

最近,我从主项目数据为CSV存储使用ADO数据块,同时我一直在使用Variant数据类型,而不是转换betweem串和单/双所有的时间也开始了。

我已经按照不同的存储器中保存的提示,我可以找到等等,其中实际我已经删除了Application.CreateForm(TProject,项目); 从.dpr并动态创建这些语句。 (除非该形式正在使用的大部分时间反正)。 Generaly我用最小的实际数据类型(字节,ShortString短等),并最大限度地减少使用“公共”变量和函数

任何提示非常欢迎,布赖恩

Answer 1:

我怀疑你是显示的代码,是问题的根源。 这可能是其中一个症状出现的地方。

如果你怀疑你有其实,一些基本的低层次的腐败,你可能想尝试打开FastMM的完全调试模式。 例如,像你遇到一个问题可以通过一般的内存堆损坏,而不是实际运行内存不足造成的。

如果你没有堆损坏,而是有真正的内存不足的问题,然后找到并解决它通常需要一个合适的工具,称为分析器,像AQTime。 也许你分配的代码是错误的方式,你可以理解,如果你简单地调试代码,并发现某处你试图抓住的内存不合理的金额,或者在一个或一系列调用一些内存分配的功能。

然而,如果没有一个分析器,如承上启下质量套房或AQTime,或其他类似工具,你将大部分失明。 您的应用程序简单地失败,堆管理代码报告是内存不足。 这可能是你在什么地方做的事情是破坏你的堆。 有可能你真的分配太多的内存为您的32位进程。 很可能你的计算机没有足够的真实的或虚拟内​​存,或您分配,你有没有意识到一个巨大的数据结构是不实际的,你的应用程序中。



Answer 2:

EOutOfMemory当内存管理器无法找到的内存对于给定的分配请求的contigious块时发生。 所以,你要么1)分配更多的内存比您预期,2)泄露你已经成功地分配内存,或3)欠缺(不一定泄漏)内存,使内存管理器必须保持一段时间分配越来越多的内存。

当发生异常时,看看调用堆栈。 这将导致你未能成功地分配内存的代码。 要获得调用堆栈,在调试器中运行你的应用程序,或使用像MadExcept,EurekaLog,JCLExcept等异常日志框架



Answer 3:

你有没有安装完整版的FastMem内存管理器? 它可以帮助您跟踪内存处理错误。 看看你是否正在泄漏的东西。

如果你没有,你有一个非常极端的碎片问题的泄漏,就必须通过维护对象池而不是保持分配/解除分配它们来对付它。



Answer 4:

为了找到你需要寻找的所有对象的创建,而不只是在异常升高OutOfMemory异常的原因。

像EurekaLog第三部分工具可以告诉你实例化的应用和没有正确地放置的所有对象。 您可以尝试使用他们终于尝试用FreeAndNil程序块纠正。



Answer 5:

听起来像内存泄漏。

我总是添加

  {$IFDEF DEBUG}
    ReportMemoryLeaksOnShutdown := DebugHook <> 0;
  {$ENDIF}

为我调试项目源文件的基础之上。

这给出了如何我已经建立了程序一个很好的迹象。



文章来源: Delphi: How to find and fix an EOutOfMemory Error?