OutofMemory Issue

qex

Regular
Joined
Apr 2, 2003
Messages
78
I've been chasing down memory leaks here recently and I have come to a point where I'm not sure what is causing it. I have a main form and then a child form that I create and do a showDialog() call some function is performed and then the form closes and I call Dispose(). I've found most of my memory leaks because it used to crash the system after about 25 seperate calls to this form... now it takes about 200.

I've been using a Memory profiler by AutmatedQA and it says that all the Live instances of this form are gone after completion, but when I look at the task manager I see three things which may or may not be related and that is the non-paged memory keeps increasing and the number of Handles and Threads for this app keep increasing... The number of threads by about 10 each time the form is run and handles 15-25.

Does anyone have any comments, suggestions, ideas.

Thanks
 
The only way you can really run into a memory leak in .Net is by allocating lots of unmanaged resources and not releasing them (either that or accidentally maintaining references to loads of managed objects).

Look at the form's code. Does it create IDisposable objects and not dispose of them? Keeping a reference to IDisposable objects and calling their Dispose or Close method is a must. If, for example, you create GDI/GDI+ objects in the OnPaint method or Paint event and forget to dispose them, you are going to run into problems. Keep an eye out for particularly large objects, such as bitmaps or huge XML documents.
 
marble_eater thanks for the reply... Yeah I've been going through the code and have put any objects that reference the IDisposable interface in a try...catch...finally block to ensure that they are getting disposed of.

Do you know for instance what type of objects would create a new thread. The only threads I explicitly create are using ThreadPool, so it must be some other interaction that is creating these threads... For example if a timer was not disposed of would that not be another thread... are there any other objects which create threads? Does creating an EventHandler create a new thread?
 
That's a good question about the EventHandler...I hoping M.E. has some input on that but I can say I've seen some issues w/Visual Studio itself when I added handlers to detected when a particular object was dropped on a web form in design view and didn't properly remove those handlers...but that's custom control development, I don't know if the same rules apply. You can try removing the handlers prior to disposing and see what you get. But I would think when the form disposes itself it removes all references to any handlers - but at the same time another object whose referencing an event maybe promoting the object to generation 2 in GC and keeping it from being de-referenced, I may be way over thinking this too and I'm no expert in GC; M.E. is pretty smart, there be something there for both of us to learn from...M.E.?
 
If you are worried about threads, I would focus on objects where you are making asynchronous calls, like Control.BeginInvoke(). Generally, I don't think that simply instantiating most objects will create another thread. Also, perhaps if you are doing some serious multithreading, the thread pool might be creating more threads for you. Honestly, I don't know too much about multithreading and I'm really just speculating here.

What does this form that is suspected of causing memory leaks do? Does it use alot of any sort of uncommon resource or some sort of class you are new to? Third party libraries? Are you using any particularly "creative" programming techniques? Especially double check frequently called functions, but that is not necessarily where the problem lies.
 
Never having used AutomatedQA I'm not sure what information it makes available to you - hopefully it should allow you to track the types / size of objects allocated, and more importantly where they where allocated.

CLR Profiler is a free tool from MS that can provide an awful lot of information about the memory usage of your app and I would definitely recommend having a look at it.

Does the number of threads allocated keep increasing or does it level out after a particular number is reached? What kind of objects are you instantiating (either using directly or using on a ThreadPool thread)?
 
Last edited:
Yeah, thats why I finally had to ask the question because AutomatedQA shows that there are no live(in memory) instances of my form class. Which should mean that there is not memory leak, but when I run the program and create and dispose of the form each time I do it the number of handles increases by 15-25 and the number of threads increases by 10. The numbers do not level out and eventually the application will crash with the System.outofmemory exception.

I will try the CLR profiler to see if it gives me any new information

As for what I'm creating the thread is used to pull together information to do a print job.
 
I did finally get something in one of my logs... I think this occurs because the system runs out of threads or thread handles... is that about right?
Code:
3/23/2006 5:14:26 PM - Exception of type 'System.OutOfMemoryException' was thrown.
3/23/2006 5:14:26 PM -    at System.ModuleHandle._GetPEKind(Int32& peKind, Int32& machine)
   at System.ModuleHandle.GetPEKind(PortableExecutableKinds& peKind, ImageFileMachine& machine)
   at System.Reflection.Module.GetPEKind(PortableExecutableKinds& peKind, ImageFileMachine& machine)
   at System.Reflection.Assembly.ComputeProcArchIndex()
   at System.Reflection.Assembly.GetName(Boolean copiedName)
   at System.Reflection.Assembly.GetName()
   at System.Windows.Forms.ThreadExceptionDialog..ctor(Exception t)
   at System.Windows.Forms.Application.ThreadContext.OnThreadException(Exception t)
   at System.Windows.Forms.Control.WndProcException(Exception e)
   at System.Windows.Forms.Control.ControlNativeWindow.OnThreadException(Exception e)
   at System.Windows.Forms.NativeWindow.Callback(IntPtr hWnd, Int32 msg, IntPtr wparam, IntPtr lparam)
   at System.Windows.Forms.UnsafeNativeMethods.DispatchMessageW(MSG& msg)
   at System.Windows.Forms.Application.ComponentManager.System.Windows.Forms.UnsafeNativeMethods.IMsoComponentManager.FPushMessageLoop(Int32 dwComponentID, Int32 reason, Int32 pvLoopData)
   at System.Windows.Forms.Application.ThreadContext.RunMessageLoopInner(Int32 reason, ApplicationContext context)
   at System.Windows.Forms.Application.ThreadContext.RunMessageLoop(Int32 reason, ApplicationContext context)
   at System.Windows.Forms.Form.ShowDialog(IWin32Window owner)
   at System.Windows.Forms.Form.ShowDialog()
   at App.OrderEntry.printOrder(callPrintRoutine& myPrintRoutine, Thread PrintingThread)
   at App.OrderEntry.finishOrder()
 
Last edited by a moderator:
Visual Basic:
mainOrderdbf.AppendRecord()
LogOrderCreatedinXFERSTAT(mainOrderdbf)
OrderComplete = True
OrderActive = False
myPrintRoutine.ordernumber = mainOrderdbf.track '_Order_Data_0.Text     'sends the order number(tracking) to the print routine
If (ThreadPool.QueueUserWorkItem(New WaitCallback(AddressOf myPrintRoutine.LoadPrintRoutine), New Object)) Then

End If
'PrintingThread.Start()
Dim myProgressBar1 As New ProgressBar("Printing Requisition", 500, True, "Printing... Please Wait")
myProgressBar1.ShowDialog()
myProgressBar1.Close()
myProgressBar1.Dispose()
AppConfiguration.Save2Config("OrderDbf", OrderDbf, OrderDbf.GetType)   'name of last orderfile used saved to config file
 
Last edited by a moderator:
Thats the code from printOrder()... it Writes the order to the database then spawns the thread which will open the data and print it.

The thing is that error doesn't occur until the code has run about 200 times.
 
Last edited:
Are you just using the ThreadPool to start threads or are you actually using the PrintingThread thread anywhere?

Also what happens in the myPrintRoutine.LoadPrintRoutine method? Does it do anything with threads / threading?
 
Yeah that error is before I made a change I was worried that I was doing something incorrectly with the System.Thread which is what PrintingThread was so I changed it to use a ThreadPool instead. So to answer PrintingThread is not used at all anymore.

Inside the LoadPrintRoutine I don't create any threads using threadPool or System.Thread.
 
Ok, I found most of my problem... very poor job on my part.

What I did was in my printing class I created a data handler class which creates instances of other classes which access my data. Each of these data classes initializes a log class which has a timer. What I did was new() the data object then set it equal to an instance of the object I passed in to the method so I was cutting of the previous instance of the timer that I just did a new() on. So I had a bunch of timers that weren't getting disposed of.

I still have some to find but my guess is its something similar.

thanks guys for your help. If nothing else I learned a little bit more about GC and some of the things not to do.
 
Back
Top