Delphi: How to find and fix an EOutOfMemory Error?

Hamish_Fernsby picture Hamish_Fernsby · Apr 5, 2012 · Viewed 7.7k times · Source

I'm building a delphi application which does scientific simulation. It's growing in complexity & now consists of many units and forms.

I'm starting to get EOutOFMemory Errors each time I run. It seems to happen during or just after I use an Array of variant temporarily within a functions. At risk of asking a really dumb question, is "array of variant" asking for trouble? ( I could convert everything to string, but array of variant in principle saves a lot of fudging things).

the offending array use might be:

 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);

In task manager - peak memory usage is 42MB, VM is 31M and I'm getting ~90,000 page faults per run. (on an xp machine with 3GB ram)

Does anyone have any general tips on monitoring memory usage by the different components within my application? or on tracing the cause of this error?

Recently I've gone from storing the main project data as CSV to using ADO DBs, At the same time I've also begun using the Variant data type rather than converting betweem string and single/double all the time.

i've followed various memory saving tips I can find like, where practical I've removed the Application.CreateForm(TProject, Project); statements from the .dpr And creating them dynamically. (except where the forms are being used most of the time anyway). Generaly I use smallest practical datatype (byte, shortstring, etc) and minimise use of 'public' variables & functions

any tips very welcome, Brian

Answer

Remy Lebeau picture Remy Lebeau · Apr 5, 2012

EOutOfMemory occurs when the memory manager cannot find a contigious block of memory for a given allocation request. So you are either 1) allocating more memory than you are expecting, 2) leaking memory you have successfully allocated, or 3) fragmenting (not necessarily leaking) memory so the memory manager has to keep allocating more and more memory over time.

When the exception occurs, look at the call stack. That will lead you to the code that is failing to allocate memory. To get the call stack, run your app in the debugger, or use an exception logging framework like MadExcept, EurekaLog, JCLExcept, etc.