Delphi:如何查找和修复EOutOfMemory错误?

Ham*_*sby 6 delphi vcl pascal

我正在构建一个进行科学模拟的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);
Run Code Online (Sandbox Code Playgroud)

在任务管理器中 - 峰值内存使用量为42MB,VM为31M,每次运行时出现约90,000页错误.(在3GB内存的xp机器上)

有没有人有关于监视我的应用程序中的不同组件的内存使用情况的一般提示?或者追踪此错误的原因?

最近我已经将主项目数据存储为CSV到使用ADO DB,同时我也开始使用Variant数据类型,而不是一直转换字符串和单/双.

我已经遵循了各种内存保存技巧,我可以找到,实际上我删除了Application.CreateForm(TProject,Project); 来自.dpr的语句并动态创建它们.(除非大部分时间都在使用表格).通常我使用最小的实用数据类型(byte,shortstring等)并最小化'public'变量和函数的使用

Brian,非常欢迎任何提示

Rem*_*eau 10

EOutOfMemory当内存管理器无法为给定的分配请求找到一个有用的内存块时,就会发生这种情况.因此,您要么1)分配比您预期更多的内存,2)泄漏您已成功分配的内存,或3)分段(不一定泄漏)内存,以便内存管理器必须不断分配越来越多的内存.

发生异常时,请查看调用堆栈.这将导致您无法分配内存的代码.要获取调用堆栈,请在调试器中运行应用程序,或使用MadExcept,EurekaLog,JCLExcept等异常日志记录框架.

  • 碎片化是一种似是而非的解释.但是知道哪个分配失败很少有助于解释内存如何变得支离破碎. (2认同)

War*_* P 3

我怀疑您所显示的代码是问题的根源。这可能是症状出现的地方。

如果您怀疑实际上存在一些基本的低级损坏,您可能需要尝试打开 FastMM 的完全调试模式。例如,像您遇到的问题可能是由一般内存堆损坏引起的,而不是实际内存不足。

如果您没有堆损坏,而是真正遇到内存不足问题,那么查找并解决它通常需要一个适当的工具,称为分析器,例如 AQTime。也许你的分配代码是错误的,如果你只是调试你的代码,并发现你试图在某个地方获取不合理的内存量,无论是在一次调用还是在对某些内存分配函数的一系列调用中,你都可以理解。

然而,如果没有分析器,例如 Nexus 质量套件或 AQTime,或其他类似的工具,您将基本上是盲目的。您的应用程序只是失败了,堆管理代码报告内存不足。您可能正在某个地方做一些破坏堆的事情。您可能确实为 32 位进程分配了太多内存。您的计算机可能没有足够的实际或虚拟内存,或者您在应用程序中分配了一个巨大的数据结构,但您没有意识到这是不实用的。