Search code examples
delphipascalvcl

Delphi: How to find and fix an EOutOfMemory Error?


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


Solution

  • I doubt that the code you are showing, is the source of the problem. It is probably a place where a symptom occurs.

    If you suspect that you have in fact, some basic low level corruption, you might want to try turning on FastMM's Full Debug Mode. For example, problems like the one you're encountering could be caused by general memory heap corruption instead of actually running out of memory.

    If you do not have heap corruption, but instead have a true out of memory problem, then finding and solving it usually requires a proper tool, called a profiler, like AQTime. Perhaps your allocation code is wrong in a way you can understand if you simply debug your code, and find that somewhere you are trying to grab an unreasonable amount of memory, either in one, or a series of calls to some memory-allocation function.

    However, without a profiler, such as nexus quality suite or AQTime, or another similar tool, you will be mostly blind. Your application is simply failing and the heap management code is reporting it is out of memory. It is possible that you are doing something somewhere that is corrupting your heap. It is possible you are really allocating too much memory for your 32 bit process. It is possible your computer does not have enough real or virtual memory, or that you are allocating a huge data structure that you have not realized is not practical, within your application.