Salesforce

Memory leak when using nested method calls.

« Go Back

Information

 
TitleMemory leak when using nested method calls.
URL NameProgress-Data-DataType-instances-left-in-memory-after-closing-UltraGrid-form
Article Number000113173
EnvironmentProduct: OpenEdge
Version: 11.3.3, 11.4.x, 11.6.x, 11.7.0, 11.7.1, 11.7.2, 11.7.3
OS: Windows
Question/Problem Description
Memory leak when using nested method calls.

AVM holds references to .NET objects depending on nesting of method calls, resulting in a memory leak.

Scenario #1
When doing a .NET method call where one of the parameters is a .NET Enum, that itself comes from a method call, the Enum instance is never garbage collected.

Where the Enum is one of the Progress.Data.DataType Enum values, Progress.Data.DataType instances are left in memory after closing UltraGrid form.

For each Column in an Infragistics UltraGrid, a Progress.Data.DataType object is created. However after closing the Form with the UltraGrid, 13 Progress.Data.DataType instances are left in memory.  These objects appear to be a leak and can be seen in the ANTS Memory profiler tool:

User-added image


Scenario #2
In this statement:

ReportDocument:PaperSize = CAST(System.Enum:ToObject(clsType, THIS-OBJECT:GetPaperSize():RawKind), System.Drawing.Printing.PaperKind ).


The reference to "THIS-OBJECT:GetPaperSize():RawKind" ends leaking System.Drawing.Printing.PrinterSettings objects and related .NET class instances.

4GL DYNOBJECTS     Created        Progress.Lang.Object    Handle:1000 (stub.p @ 26) Report
4GL DYNOBJECTS     Created        Progress.Lang.Object    Handle:1001 (Report Report @ 40) ReportDocument
4GL DYNOBJECTS     Created-Ref    .NET Object             Handle:1002 (Print Report @ 70)  Pool:<Session Pool>
4GL DYNOBJECTS     Created        .NET Object             Handle:1004 (GetPaperSize PrinterUtil @ 32) System.Drawing.Printing.PrinterSettings Pool:<Session Pool>
4GL DYNOBJECTS     Created        .NET Object             Handle:1005 (GetPrinterDefaultPaperSize PrinterUtil @ 47) System.Drawing.Printing.PrinterSettings Pool:<Session Pool>
4GL DYNOBJECTS     Created-Ref    .NET Object             Handle:1006 (GetPrinterDefaultPaperSize PrinterUtil @ 52)  Pool:<Session Pool>
4GL DYNOBJECTS     Created-Ref    .NET Object             Handle:1007 (GetPrinterDefaultPaperSize PrinterUtil @ 52)  Pool:<Session Pool>

4GL DYNOBJECTS     Created-Ref    .NET Object             Handle:1008 (Print Report @ 78)  Pool:<Session Pool>
4GL DYNOBJECTS     Deleted        .NET Object             Handle:1002 (Print Report @ 88)
4GL DYNOBJECTS     Deleted        Progress.Lang.Object    Handle:1000 (stub.p @ 38) Report
4GL DYNOBJECTS     Deleted-by-GC  Progress.Lang.Object    Handle:1001 (stub.p @ 38) ReportDocument
4GL DYNOBJECTS     Deleted-by-GC  .NET Object             Handle:1008 (stub.p @ 38) System.Drawing.Printing.PaperKind


These objects should be caught and cleaned up by garbage collection.

The leak does not occur if an intermediate variable is used to store the result of the method call, e.g.

iTempy = THIS-OBJECT:GetPaperSize():RawKind.
ReportDocument:PaperSize = CAST(System.Enum:ToObject(clsType, iTempy), System.Drawing.Printing.PaperKind).


4GL DYNOBJECTS     Created        Progress.Lang.Object    Handle:1000 (stub.p @ 26) Report
4GL DYNOBJECTS     Created        Progress.Lang.Object    Handle:1001 (Report Report @ 40) ReportDocument
4GL DYNOBJECTS     Created-Ref    .NET Object             Handle:1002 (Print Report @ 70)  Pool:<Session Pool>
4GL DYNOBJECTS     Created        .NET Object             Handle:1004 (GetPaperSize PrinterUtil @ 32) System.Drawing.Printing.PrinterSettings Pool:<Session Pool>
4GL DYNOBJECTS     Created        .NET Object             Handle:1005 (GetPrinterDefaultPaperSize PrinterUtil @ 47) System.Drawing.Printing.PrinterSettings Pool:<Session Pool>
4GL DYNOBJECTS     Created-Ref    .NET Object             Handle:1006 (GetPrinterDefaultPaperSize PrinterUtil @ 52)  Pool:<Session Pool>
4GL DYNOBJECTS     Created-Ref    .NET Object             Handle:1007 (GetPrinterDefaultPaperSize PrinterUtil @ 52)  Pool:<Session Pool>
4GL DYNOBJECTS     Deleted-by-GC  .NET Object             Handle:1006 (GetPrinterDefaultPaperSize PrinterUtil @ 52)
4GL DYNOBJECTS     Deleted-by-GC  .NET Object             Handle:1005 (GetPaperSize PrinterUtil @ 35) System.Drawing.Printing.PrinterSettings
4GL DYNOBJECTS     Deleted-by-GC  .NET Object             Handle:1004 (GetPaperSize Report @ 53) System.Drawing.Printing.PrinterSettings
4GL DYNOBJECTS     Deleted-by-GC  .NET Object             Handle:1007 (Print Report @ 85)

4GL DYNOBJECTS     Created-Ref    .NET Object             Handle:1008 (Print Report @ 86)  Pool:<Session Pool>
4GL DYNOBJECTS     Deleted        .NET Object             Handle:1002 (Print Report @ 88)
4GL DYNOBJECTS     Deleted        Progress.Lang.Object    Handle:1000 (stub.p @ 38) Report
4GL DYNOBJECTS     Deleted-by-GC  Progress.Lang.Object    Handle:1001 (stub.p @ 38) ReportDocument
4GL DYNOBJECTS     Deleted-by-GC  .NET Object             Handle:1008 (stub.p @ 38) System.Drawing.Printing.PaperKind

 

Steps to ReproduceUsing code from the attached repro.zip file:

Run stub.p with client-logging for Dynobjects.*:4 enabled

prowin -p stub.p -clientlog leak.log -logentrytypes dynobjects.*:4

Review client log to see far more CREATE* entries than DELETE* entries.

Comment/uncomment code in the Report.cls

Rerun test.

prowin -p stub.p -clientlog noleak.log -logentrytypes dynobjects.*:4

Review client log to see an almost equal number of CREATE* entries and DELETE* entries.
Clarifying Information
Leaking objects can be seen in both the client log and the SESSION:FIRST-OBJECT/NEXT-SIBLING chain.

Issue is not specific to Enum classes. It applies to any case where a temporary object is instantiated during the evaluation of a method's parameters (including a constructor method).

This issue does not seem to be corrected by trying to DELETE the objects explicitly.
 
Error Message
Defect NumberOCTA-7599
Enhancement Number
Cause
The AVM is holding on to references to .NET objects depending on nesting of method calls, resulting in a memory leak.

This issue was introduced in OpenEdge 11.3.3, 11.4 and all versions prior 11.7.3.012 where defect PSC00292517 was fixed, to avoid deleting parameter objects prematurely but ended up with a leak.
Refer to article#  Method that returns .NET object fails when calling method to resolve parameter.
 
Resolution
Fixed version(s): 11.7.4.0, 12.0.0.0, 11.7.3.013
Workaround
Use intermediate variables instead of nesting the method calls inside the parameters.
iTempy = THIS-OBJECT:GetPaperSize():RawKind. 
​ReportDocument:PaperSize = CAST(System.Enum:ToObject(clsType, iTempy), System.Drawing.Printing.PaperKind).
Notes
Keyword Phrase
Last Modified Date10/23/2023 12:10 PM

Powered by