cancel
Showing results for 
Search instead for 
Did you mean: 

Reproducible error when loading many reports (Load report failed -> Not enough memory for operation)

Former Member
0 Kudos

Environment:

Win 7 SP 1

Visual Studio Pro 2012 Update 4

Crystal Reports for Visual Studios Service Pack 10 (13.0.10.1385)

Report created in Crystal Reports XI Release 2 (11.5.8.826)

Targeting x86 .NET 4.0

Scenario:

We have a program that runs and creates a large number of reports before the process is ended. When running after many hours we'd get a Load report failed/Not enough memory of operation exception. I kept removing code and found i could reproduce just using the report.Load call. I simplified the report to a completely blank report to make sure it was nothing specific to a report I was loading. (Opened Crystal Reports XI Release 2, Save As, "Blank.rpt".). I then created, loaded, and disposed of this report in a loop. I was able to cause the same exception after 32,764 iterations on my machine. I also tried using .NET 3.5 same result. I added a counter to our main program and it also went through 32,764 report loads before the same exception was thrown. Main program uses 15 or so different reports with a variable number of subreports in each.

Sample Code to illustrate the problem:

I did this as a WinForms project since our main program is using winforms.

References added:

CrystalDecisions.CrystalReports.Engine

CrystalDecisions.ReportSource

CrystalDecisions.Shared

CrystalDecisions.Windows.Forms

using System;

using System.Windows.Forms;

using CrystalDecisions.CrystalReports.Engine;

namespace CrystalTest

{

    public partial class Form1 : Form

    {

        public Form1()

        {

            InitializeComponent();

            int i = 0;

            try

            {

                while (true)

                {

                    i++;

                    ReportDocument report = new ReportDocument();

                    report.Load("Blank.rpt");

                    report.Close();

                    report.Dispose();

                }

            }

            catch(Exception ex)

            {

                MessageBox.Show(i.ToString() + ex.Message);

            }

        }

    }

}

Exception:

CrystalDecisions.Shared.CrystalReportsException: Load report failed. ---> System.Runtime.InteropServices.COMException (0x80041004):

Not enough memory for operation.

   at CrystalDecisions.ReportAppServer.ClientDoc.ReportClientDocumentClass.Open(Object& DocumentPath, Int32 Options)

   at CrystalDecisions.ReportAppServer.ReportClientDocumentWrapper.Open(Object& DocumentPath, Int32 Options)

   at CrystalDecisions.ReportAppServer.ReportClientDocumentWrapper.EnsureDocumentIsOpened()

   --- End of inner exception stack trace ---

   at CrystalDecisions.ReportAppServer.ReportClientDocumentWrapper.EnsureDocumentIsOpened()

   at CrystalDecisions.CrystalReports.Engine.ReportDocument.Load(String filename, OpenReportMethod openMethod, Int16 parentJob)

   at CrystalDecisions.CrystalReports.Engine.ReportDocument.Load(String filename)

   at CrystalTest.Form1..ctor() in c:\Test Projects\CrystalTest\CrystalTest\Form1.cs:line 27

Accepted Solutions (1)

Accepted Solutions (1)

0 Kudos

Hi Phil,

Try adding in some delay between loads, it could be you need to let the OS catch up. There are known memory leaks, majority of them are in Windows dll's, a simple test like this typically will show CR has about a 6k leak. Windows has Meg's of leaks.

Another question is 32K could be a limitation of how you have the counter defined, if it's an Int try changing it to Int32 or Int64...

If you are going to do report bursting like this then create a threading app and load each report in it's own process, when the process is closed or killed it will release the memory as well.

And you will run into limitations. CR for VS allows 3 reports to be loaded at one time and that is it. For high volume report processing you should go to CRSE ( OEM) or CR Server for more RAS servers limited to one PC then to BI 4.1 which you can specify the number of RAS Server based on CPU's and add more PC's to add more RAS Servers. They run as a service, you can then add more RAS Servers according to your loads.

Use something like Ration Purify or some other memory test tool and you'll see it's not CR that is main consumer of memory.

Don

PS - took out the part about why.... You already said why...

Former Member
0 Kudos

In our real life we load a report, fill datasets based on what the report needs to show, then we map the dataset to the report, then we export the report to PDF. So the report is created, loaded, populated with data, exported to pdf, and then closed and disposed. The number of reports is based on the number of rows in an sql table. Additional data is fetched then massaged a bit before loading into the different reports.

The point of this test was to show the problem in the simplest terms using the smallest amount of code to help illustrate the problem.

As for a memory leak, the process only hits about 40-50 megs total. It will stay at about that value for the entire duration of the test. So this isn't really a memory leak from what I can tell. It may be based in heap fragmentation, but I wasn't able to find evidence of that.

OS catch up isn't a problem, in the real scenario printing the 32000 reports takes well over 8 hours once you take the export to pdf into account as well as the pulling of the data.

I'm only loading one report at a time in both this example and the real world program. Once the report is exported to pdf its job is done and it is closed and disposed. This also avoids the 75 print job limit.

Former Member
0 Kudos

Forgot to mention. The counter is the variable "i" which is incremented inside the loop and displayed in the Messagebox at the bottom.

0 Kudos

Hi Phil,

In the main app you should also be cleaning up, closing/disposing the Datasets also then. Assuming they are being updated.

And can you change "i" to Int32 or Int64... Just curious if it's the counter causing the problem in the test app.

BUT.... Forget the test app, it really isn't anything like real life and simply shows there is some kind of limit somewhere and I suspect it's just an internal or external counter.

What is the actual issue you are having and after how many report jobs?

Is is consistent?

Check your \system\temp folder, are there any file being left behind?

Don

Former Member
0 Kudos

int = Int32. No it's not the "counter" that's causing the problem. The max size of an int32 is far far larger than 32764.

I am disposing and cleaning up the datasets in the main app. That is why I didn't include them in this test; they aren't relevant.

I'm unsure why this test program is completely irrelevant. It throws the same exception, at the same count, as the main program. It does it in substantially less lines of code than our main program. I spent days running long tests to figure out exactly what I needed to make the problem appear so I could post a clean and precise post on these forums. I then created the test program to illustrate that.

The "real" code as I said does stuff in sections and in a certain order.

For each report I need to export based on rows in a table

1. Creates a new Report Document

2. Loads the report document with the report

3. Creates a dataset of the data to display

4. Calls SetDataSource

5. Calls Report.ExportToDisk

6. Disposes DataSets

7. Closes/Disposes Reports

To help isolate the problem I first took out the export to disk part (Step 5). The problem still occurred. I then took out everything related to our data. (Step 3, Step 4, Step 6). The problem still occurred. And yes I commented out this code in our main real program. This left me with:

1. Creates a new Report Document

2. Loads the report document with the report

7. Closes/Disposes Reports

At this point i had to prove it was not dependent on the report. This makes sure it's not a database connection, or pulling too much data into the report. The most efficient test for this is a blank report.

So my order of operations becomes...

1. Creates a new Report Document

2. Loads the report document with a blank report

7. Closes/Disposes Reports

So you'll see this is exactly why I wrote this test the way that I did.

I've had a run where it error on iteration 32761. My last runs have errored on 32764. I have had many runs over many weeks that all error with the same exception.

There are no temp files left behind, With a test running you can see the temp files being added but they are immediately removed.

Answers (1)

Answers (1)

Former Member
0 Kudos

I have encountered the same problem, so I was wondering if you might have found a solution?

my exception is :

Exception: Server is out of memory.

Stack trace:    at CrystalDecisions.ReportAppServer.Controllers.SubreportControllerClass.GetSubreport(String Name)

   at CrystalDecisions.CrystalReports.Engine.DataDefinition.get_ParameterFields()

   at CrystalDecisions.CrystalReports.Engine.ReportDocument.SetParameterValue(String name, Object val)

former_member183750
Active Contributor
0 Kudos

Boris, is the issue exactly the same? E.g.; are you running a high number of reports in a loop?

What version of .NET?

What SP for CRVS are you using?

Are you doing all the suggestions in this thread? E.g.; close dispose the report object, close dispose the dataset. Checked the temp folder to see if the cr temp files are being cleaned up?

Can you duplicate the issue as Phil was able to by running a report with no database connection (no dataset either) and just load:

1. Creates a new Report Document

2. Loads the report document with a blank report

3. Closes/Disposes Reports

- Ludek

Senior Support Engineer AGS Product Support, Global Support Center Canada

Follow me on Twitter

Got Enhancement ideas? Use the SAP Idea Place

Former Member
0 Kudos

Ludek,

In my original project I am running Report export to PDF in a loop.(It has processes in between Report.export so it has time shift)

I have to add, the first like 32000 reports are created correctly.

Yes I have tried exactly the same procedure(test.rpt is blank report).

int i = 0;

try

{

  while (true)

  {

  i++;

  label1.Text = i.ToString();// just to show number of reports.

  ReportDocument report = new ReportDocument();

  report.Load(@"C:\Projects\test\test\test.rpt");

  report.Close();

  report.Dispose();

  }

}

catch (Exception ex)

{

  MessageBox.Show(i.ToString() + ex.Message);

}

I also tried after Dispose adding

  GC.Collect();

in different run i tried adding this

  report=null;

  GC.Collect();

  GC.WaitForPendingFinalizers();

  GC.Collect();

nothing helped.

It's like You have embedded in Crystal Reports short int counter and when it comes to max value 2^15 it stops working and throws exception "system out of memory".

I am using:

Visual studio 2010, Version 10.0.40219.1 SP1Rel

.NET ,Vesion 4.5.51209 SP1Rel

SAP BusinessObjects Enterprise XI 4.0, Version 13.0.4.705

I have encountered 3 kinds of exceptions,

First one:

Exception: Server is out of memory.

Stack trace:    at CrystalDecisions.ReportAppServer.Controllers.SubreportControllerClass.GetSubreport(String Name)

   at CrystalDecisions.CrystalReports.Engine.DataDefinition.get_ParameterFields()

   at CrystalDecisions.CrystalReports.Engine.ReportDocument.SetParameterValue(String name, Object val)

Second one:

Exception: The Report Application Server failed

Inner exception: The Report Application Server failed

Stack trace:    at CrystalDecisions.ReportAppServer.ConvertDotNetToErom.ThrowDotNetException(Exception e)

   at CrystalDecisions.ReportSource.EromReportSourceBase.ExportToStream(ExportRequestContext reqContext)

   at CrystalDecisions.CrystalReports.Engine.FormatEngine.ExportToStream(ExportRequestContext reqContext)

   at CrystalDecisions.CrystalReports.Engine.FormatEngine.Export(ExportRequestContext reqContext)

   at CrystalDecisions.CrystalReports.Engine.FormatEngine.Export()

   at CrystalDecisions.CrystalReports.Engine.ReportDocument.Export()

And the third one(it continues while counter runs out) :

Exception: Load report failed.

Inner exception:

Not enough memory for operation.

Stack trace:    at CrystalDecisions.ReportAppServer.ReportClientDocumentWrapper.EnsureDocumentIsOpened()

   at CrystalDecisions.CrystalReports.Engine.ReportDocument.Load(String filename, OpenReportMethod openMethod, Int16 parentJob)

   at CrystalDecisions.CrystalReports.Engine.ReportDocument.Load(String filename)

Former Member
0 Kudos

Hey Boris, If you follow me I can send you a direct message.