Memory leak that I can't find. Please help!

I am having a problem with an application that I'm working on.  I am fairly certain that it is a memory leak pertaining to bitmaps from my file.  I've tried and tried to find the leak to no avail.  

The application that I'm creating is essentially a go between for two other programs.  The two programs are:
1. An online hosted game
2. A logic application that logs the past outcome of the game and provides suggestions for the next move

My application does the following:
1. Reads the current outcome of the game
2. Passes the information to the logic application and forces the logic app to update with a new suggestion
3. Based on the suggestion, interacts with the online game

The problem is that neither of these applications have any sort of API, and the only way that I can perform this is by strategically locating the applications on the same section of the screen during each play and comparing screen captures to the potential outcomes for each application.

I have my program working properly, except for the fact that after a certain number of iterations of playing the game, it breaks and throws a "Parameter is Not Valid" error when performing a routine screen capture.  From looking online, I've found out that this is a generic error and most likely means that there is a memory leak.  Further supporting the memory leak hypothesis is that if you Try...Catch the error and let the application continue to run, you will get an OutOfMemory error.

I've tried to eliminate this error through hours and hours of debugging, but I'm relatively new trying to catch these errors, and I can't find it.  

I have attached two files:
1. The Action Form doc shows the code of the form that is performing the loop
2. The Helper Information doc shows the class structures and additional helper code

I would greatly appreciate your assistance in getting my code running correctly without errors.  Also, I'd be happy to let anyone look at the source code if that helps in debugging the leak


P.S. I writing in VB.NET, using Framework 3.5, and running Windows XP.  I've tried this on two computers and have the same problem so I don't think it is a hardware issue.  
Who is Participating?
MrSlausenConnect With a Mentor Author Commented:
This issue has been resolved.  The issue is that the .NET framework has a bug with the CopyFromScreen() method that creates unnecessary handles.  The solution is to go back to the Windows API for the screenshot.  Below is an example of the VB version of the code that I used to correct the issue.

<DllImport("gdi32.dll")> _
Public Shared Function BitBlt(ByVal hdcDest As IntPtr, ByVal xDest As Integer, ByVal yDest As Integer, ByVal wDest As Integer, ByVal hDest As Integer, ByVal hdcSource As IntPtr, ByVal xSrc As Integer, ByVal ySrc As Integer, ByVal rop As Drawing.CopyPixelOperation) As End 
<DllImport("user32.dll")> _
Public Shared Function ReleaseDC(ByVal hWnd As IntPtr, ByVal hDc As IntPtr) As Boolean
End Function
<DllImport("gdi32.dll")> _
Public Shared Function DeleteDC(ByVal hDc As IntPtr) As IntPtr
End Function
<DllImport("gdi32.dll")> _
Public Shared Function DeleteObject(ByVal hDc As IntPtr) As IntPtr
End Function
<DllImport("gdi32.dll")> _
Public Shared Function CreateCompatibleBitmap(ByVal hdc As IntPtr, ByVal nWidth As Integer, ByVal nHeight As Integer) As IntPtr
End Function
<DllImport("gdi32.dll")> _
Public Shared Function CreateCompatibleDC(ByVal hdc As IntPtr) As IntPtr
End Function
<DllImport("gdi32.dll")> _
Public Shared Function SelectObject(ByVal hdc As IntPtr, ByVal bmp As IntPtr) As IntPtr
End Function
<DllImport("user32.dll")> _
Public Shared Function GetDesktopWindow() As IntPtr
End Function
<DllImport("user32.dll")> _
Public Shared Function GetWindowDC(ByVal ptr As IntPtr) As IntPtr
End Function
Public Shared Function CaptureImage(ByVal width As Integer, ByVal height As Integer, ByVal x As Integer, ByVal y As Integer) As System.Drawing.Bitmap
Dim sz As Rectangle
sz.Width = width
sz.Height = height
Dim hDesk As IntPtr = appMain.GetDesktopWindow()
Dim hSource As IntPtr = appMain.GetWindowDC(hDesk)
Dim hDest As IntPtr = appMain.CreateCompatibleDC(hSource)
Dim hBmp As IntPtr = appMain.CreateCompatibleBitmap(hSource, sz.Width, sz.Height)
Dim hOldBmp = appMain.SelectObject(hDest, hBmp)
Dim b As Boolean = appMain.BitBlt(hDest, 0, 0, sz.Width, sz.Height, hSource, x, y, CopyPixelOperation.SourceCopy)
Dim bmp As Bitmap = Bitmap.FromHbitmap(hBmp)
appMain.SelectObject(hDest, hOldBmp)
appMain.ReleaseDC(hDesk, hSource)
Return bmp
End Function

Open in new window


There are a couple of products that you should try to track this down.  I just loaded the latest version of Ants profiler and was impressed with the information that it gives you.  They have a fully working 10 day demo, which should give you the time you need to evaluate the tool with a real-life problem.  

The other tool is called .NET memory profiler, which also helps you evaluate your memory usage and find leaks.

Here are the links:

Best regards,

MrSlausenAuthor Commented:
kdwood: I've used both of these products and was wondering which you think is better for debugging.  My initial take on memprofiler was that it was better for comparing snapshots, but ANTS was a little deeper.

Your thoughts as someone a little more advanced in debugging?
I agree with your initial take.  Memprofiler also provides the real-time view which is nice.   I just started using both tools a couple of weeks ago myself, so I am by no means an expert on either.

Please note, I am not expecting points for the product suggestions.  I have an unlimited account so save your points.  

Just out of curiosity, when the application bombs, look in task mgr at your running processes and see how many Excel.exe intances are running.  I've had a problem in the past with the office.interop and the objects not releasing/ending.

I'm assuming you've tried dumbing down the application to just run a couple of functions at a time on each loop.  Then add each function back in one at a time where possible, to try and narrow it down.

How big are the bitmaps from the screen capture typically?


MrSlausenAuthor Commented:
I'll keep the number of instances of running applications when using office.interop in the future.  

I think I fixed the error.  I switched from a FOR..NEXT loop to a DO...LOOP loop and I added a throttle that sleeps the thread for 20 seconds every 1000 turns.  I've tested this on the sample application and not yet on the full application with no exceptions.  I'll be testing on the full application in the next couple of days.

FYI - the bitmaps are typically very small (typically 15x10 and only a few hundred bytes).

If I still have problems in my testing in the next few days, I'll repost.

Thanks Keith for your help!


Question has a verified solution.

Are you are experiencing a similar issue? Get a personalized answer when you ask a related question.

Have a better answer? Share it in a comment.

All Courses

From novice to tech pro — start learning today.