Solved

EOutOfResources

Posted on 2004-08-23
12
1,492 Views
Last Modified: 2008-01-09
Hi,

I'm creating a server application, which will be run 24 hours a day. After some hours I run the application I get these error messages:

"Not enough storage is available to process this command" and
"Out of system resources"

Both messages were sent by exception EOutOfResources and the Sender
class is TSyncManager.

I can hardly trace and debug this error because the error always occur
while I'm away. I tried to get some more information about the exception
to get me some more idea where the bug might be located, but I cannot
find enough information about it.

Can anybody help me with some information about the exception and those error messages, what it is and what actions might cause those errors?

regards,
huferry
0
Comment
Question by:huferry
  • 4
  • 2
  • 2
  • +4
12 Comments
 
LVL 12

Expert Comment

by:esoftbg
Comment Utility
From Delphi help :
EOutOfResources is the exception class for unsuccessful attempts to allocate handles.
EOutOfResources is raised when an application attempts to create a Window or widget handle and there are no more handles to allocate.
0
 
LVL 12

Expert Comment

by:Ivanov_G
Comment Utility
it seems you have "memory leak". This mean that you are creating and object you don't free. For example:

var
  Obj: TAdoQuery;
begin
  Obj := TAdoQuery.Create(Self);
  // DO SOMETHING
  // the example above is memory leak
end;

you have to use:
  Obj := TAdoQuery.Create(Self);
  try
  // Do SOMETHING
  finally
    Obj.Free;
  end;
end;
0
 
LVL 3

Author Comment

by:huferry
Comment Utility
Ivanov G: I'm trying to debug my app for memory leak, but so far I could not find more.
esoftbg: I don't really 'playing' with handles directly.

Is there a chance that re-assigning new images to JPG files -- it happens about 50 images
per second (resolution 160x120) -- might have to do with the handles?

I use a TObject queue to put my jpgs (TJpegImage).

for example:

var
  Queue: TObjectQueue; // initialized somewhere else

procedure ReceiveNewImage(Bmp: TBitmap);
var
  Jpg: TJpegImage;
begin
  if (Queue.Count>=200) then
    Jpg := TJpegImage( Queue.Pop )
  else
    Jpg := TJepgImage.Create;

  Jpg.Assign(Bmp);

  Queue.Push(Jpg);
end;

//------
 
Is there a possibility that this causes the EOutOfResources ???

regards,
huferry
0
 
LVL 17

Expert Comment

by:Wim ten Brink
Comment Utility
Your application is just running out of resources and that's probably because you're leaking memory. The best way to find these errors is by maintaining a log file. Then, evert componet you use should write to the logfile when it is created and when it is destroyed. (And some other important events.) If possible, try to generate unique ID's for every new object.

The way I do this is by modifying the constructors and destructors of every component. Here you add code to write to the logfile.

Now, run your application for a while and then check if every component that is created is also freed sooner or later. I think in your case, you forget to free some objects, thus you run out of resources. The log will provide a hint about where it happens.

For a very useful logging method download http://www.workshop-alex.org/Sources/Debug/debug.zip from my site. This is a small project that compiles to a DLL. This DLL will write information to a specially formatted log file. Add the unit cp_Debug into your project and all you have to do is add WriteLn() statements in your code. The unit adds two new textfiles to your application. One is called "Log" and adds timestamps to every new line. The other is called "Debug" and is a plain-text file.
The advantage of using this DLL/Unit is simple. If the DLL isn't in the same folder as the executable, no log information will be generated. However, if it can find the DLL, it will load it and write all kinds of log information to two log files. (One .Log and one .Debug file.)

The code is pretty threadsafe too, btw. It has helped me quite often in detecting small errors and memory leaks and if you don't include the DLL with your final version, it won't generate any log information either.
0
 
LVL 17

Expert Comment

by:Wim ten Brink
Comment Utility
Hmmm. Checking your latest response now. It could well be that you create new JPGs faster than you destroy them. If you create 50 JPGs per second and only destroy 45 JPGs per second, then every second you just keep 5 JPGs in memory. In one minute this will have grown to 5*60=300 JPGs. An hour later you have 18000 JPGs in memory. After 5 hours it will increase to 90000 images waiting to be destroyed...

In that case, check the length of the queue... If it's past a certain limit, just let the system delay a while or speed up the process that is freeing the JPGs.
0
 
LVL 12

Expert Comment

by:Ivanov_G
Comment Utility
huferry, I don't see JPG.FREE after you are finished with the picture. You should free the object.

You can also use FreeAndNil(Jpg);
0
How your wiki can always stay up-to-date

Quip doubles as a “living” wiki and a project management tool that evolves with your organization. As you finish projects in Quip, the work remains, easily accessible to all team members, new and old.
- Increase transparency
- Onboard new hires faster
- Access from mobile/offline

 
LVL 17

Expert Comment

by:Wim ten Brink
Comment Utility
The free is not really required since the images are stored on a stack, AFAIK. Somewhere else in the code, this stack could be freed again. It keeps pushing images on the stack until there are 200 items in the stack. Then it starts reusing images from the stack.

But this limit might not be enough, though. Besides, I don't see where the BMP that is passed to this function is freed... It could well be that he's forgetting to free these bitmaps. :)
0
 
LVL 3

Author Comment

by:huferry
Comment Utility
Workshop_Alex: About the bitmaps, I get those from another third-party component (I assume that there is no leak in that component) and it's his responsibility to destroy the bitmap (after the event). And about the 5 jpgs/min in the memory, I reuse them for another images, I don't really destroy them until the application is terminated.

Ivanov G: The jpgs are freed just before the application is terminated, so I don't free them on that same method.


regards,
huferry
0
 
LVL 17

Expert Comment

by:Wim ten Brink
Comment Utility
Yeah, I noticed that you're re-using JPG's after I submitted my "brilliant" remark... :P

Still, you must be leaking memory somewhere and it could well be in the component that you're using. Try adding bmp.Free; at the end of your code and see what happens. If you're not supposed to free it, it will crash in minutes. Otherwise, it's the leak...

My experience with third-party components are that they are about as buggy as my own code. And sometimes even worse... If possible, check the sourcecode of this component to check if he's indeed freeing the bitmap.

Since it takes hours before the system crashes, I assume it's just leaking small amounts of memory all the time. In general, the system would start to slow down after a while because it starts swapping and this slowdown will lengthen the whole process a bit further before the system finally gives up. In these situations the task manager can be a great help too since it will show you the amount of memory but also the number of resources that you are using. Check if these are just growing. You don't have to sit up all night to just check the increase in memory or file handles.
But it is clear something is leaking...
0
 
LVL 3

Expert Comment

by:gandalf_the_white
Comment Utility
in my company i use sleuth codewatch for finding memory leaks
its quite easy to use and generates more messages than you wanted to get ;-)

i don't think posting code will help much as it is possible that a small helperfunction
causes the leak and it would be no good idea to post too much code as nobody would
check it as a whole (beside the copyright problems).

regards
0
 
LVL 22

Expert Comment

by:mnasman
Comment Utility
Hello

  If your application work 24/7, then it's might have memory fragmentation, Borland memory manager didn't work well for these types of application, replacing the memory manager with better one, will improve the performance and will fix a lot of these types of problems, the memory manager I suggest you to look about is the one from NexusDB, its work much better than Borland one

take a look here, download and try it
http://www.nexusdb.com/index.asp?id=3
0
 
LVL 1

Accepted Solution

by:
unordained earned 250 total points
Comment Utility
EOutOfResources isn't caused only by memory leaks. It can be caused anytime a memory allocation fails for any reason whatsoever, even if there's memory available.

Our application started experiencing these errors rather commonly when it got big. We didn't have memory leaks, and it would happen even when the application had just started up, when the user requested the first few forms -- it tends to go away after that, though it's not consistent. We created a set of #define's to place around every call to new() that involved a borland-provided class, VCL or otherwise. The #define would automatically retry (while loop) if the try/catch inside the #define caught an EOutOfResources exception (later, I think we added two or three other exceptions to the list, as they all had similar issues.) Oddly enough, the second or third loop will generally not have any errors, and our code continues to execute just fine. I've never seen it loop infinitely. The user never sees anything, either (but it's still annoying in debug mode, as the IDE catches the exception first.) As someone else pointed out, borland's memory functions may not be perfect, but don't assume it's always caused by memory leaks. In our case, it just didn't feel like allocating the new objects on the first request, but would have no trouble doing so later. I'm posting the code of these #define's below:

#define FORM_TRY {bool success = false; while (!success) {try {
#define FORM_CATCH success = true;} catch (EOutOfResources &) {} catch(EAccessViolation &) {} catch(EAbstractError &) {} catch(EReadError &) {}}}

Our code then typically looks like:

   FORM_TRY
    TformRecordRelationship * f = new TformRecordRelationship(NULL, params);
    f->Show();
   FORM_CATCH

We knew about this problem from other projects, we knew other programming teams had never found a solution to make the exceptions go away permanently, and the problem didn't appear right away. We're still using Builder5 for this project; my girlfriend is using Builder6 for some new projects and says she's not yet run into this same problem (but plenty of others.) Give it a try, see if the problem goes away with some simple retrying.
0

Featured Post

IT, Stop Being Called Into Every Meeting

Highfive is so simple that setting up every meeting room takes just minutes and every employee will be able to start or join a call from any room with ease. Never be called into a meeting just to get it started again. This is how video conferencing should work!

Join & Write a Comment

Introduction I have seen many questions in this Delphi topic area where queries in threads are needed or suggested. I know bumped into a similar need. This article will address some of the concepts when dealing with a multithreaded delphi database…
Introduction Raise your hands if you were as upset with FireMonkey as I was when I discovered that there was no TListview.  I use TListView in almost all of my applications I've written, and I was not going to compromise by resorting to TStringGrid…
This video gives you a great overview about bandwidth monitoring with SNMP and WMI with our network monitoring solution PRTG Network Monitor (https://www.paessler.com/prtg). If you're looking for how to monitor bandwidth using netflow or packet s…
This tutorial demonstrates a quick way of adding group price to multiple Magento products.

763 members asked questions and received personalized solutions in the past 7 days.

Join the community of 500,000 technology professionals and ask your questions.

Join & Ask a Question

Need Help in Real-Time?

Connect with top rated Experts

13 Experts available now in Live!

Get 1:1 Help Now