Note that there are some explanatory texts on larger screens.

plurals
  1. PODebugging OoM Exception
    primarykey
    data
    text
    <p>Edit: Added code (Exception on line 095, 5th time it's hit.)</p> <pre><code> public DataTable ParseBarcodes(String[] files, BarcodeZoneScan[] scanParameters) { message = null; //gmseBitmap img = null; gmseBitmap rotImg = null; gmseBitmap parseImage = null; gmseBitmap tempImage = null; DataTable codes = new DataTable(); codes.Columns.Add("PageNumber"); codes.Columns.Add("Text"); codes.Columns.Add("Type"); codes.Columns.Add("RegionName"); try { gmseBarcodeInfoCollection bcc; gmseBarcodeReaderParameter param = new gmseBarcodeReaderParameter(); gmseLicense.License = "plaintext license key ommited"; String dvImageName; int searchCount = 0; for (int dvCount = 0; dvCount &lt; files.Length; dvCount++) { if (cancelled) //If cancelled, end the loops { dvCount = files.Length; break; } dvImageName = files[dvCount].ToString(); using (gmseBitmap img = new gmseBitmap(dvImageName)) { int framecount = img.GetFrameCount(); for (int e = 0; e &lt; framecount; e++) { for (int j = 0; j &lt; scanParameters.Length; j++) { if (scanParameters[j].Range == PageRange.All ||//All (scanParameters[j].Range == PageRange.Even &amp;&amp; (searchCount == 0 || searchCount % 2 == 0)) || //even (scanParameters[j].Range == PageRange.Odd &amp;&amp; (searchCount != 0 &amp;&amp; searchCount % 2 != 0)) || (scanParameters[j].Range == PageRange.First &amp;&amp; searchCount == 0)) { //Setup what barcodes are going to be search for param.BarcodeType = 0; if (scanParameters[j].BarcodeTypes == BarcodeType.All) //All { param.BarcodeType = (int)gmseBarcodeType.All; } else { if ((scanParameters[j].BarcodeTypes &amp; BarcodeType.Code39) != 0) //Code 39 param.BarcodeType = param.BarcodeType | (int)gmseBarcodeType.Code39; if ((scanParameters[j].BarcodeTypes &amp; BarcodeType.Code11) != 0) //Code 11 param.BarcodeType = param.BarcodeType | (int)gmseBarcodeType.Code11; if ((scanParameters[j].BarcodeTypes &amp; BarcodeType.Code93) != 0) //Code 93 param.BarcodeType = param.BarcodeType | (int)gmseBarcodeType.Code93; if ((scanParameters[j].BarcodeTypes &amp; BarcodeType.Code128) != 0) //Code 128 param.BarcodeType = param.BarcodeType | (int)gmseBarcodeType.Code128; if ((scanParameters[j].BarcodeTypes &amp; BarcodeType.Ean8) != 0) //EAN 8 param.BarcodeType = param.BarcodeType | (int)gmseBarcodeType.EAN8; if ((scanParameters[j].BarcodeTypes &amp; BarcodeType.Ean13) != 0) // EAN 13 param.BarcodeType = param.BarcodeType | (int)gmseBarcodeType.EAN13; if ((scanParameters[j].BarcodeTypes &amp; BarcodeType.I2of5) != 0) //I2of5 param.BarcodeType = param.BarcodeType | (int)gmseBarcodeType.i2of5; } param.IgnoreCheckSum = 1; param.ReadMode = gmseBarcodeReadMode.WholeBitmap; using (rotImg = new gmseBitmap(img.ExtractFrame(e))) { // do some basic image enhancement for better results rotImg.ChangePixelFormat(System.Drawing.Imaging.PixelFormat.Format32bppArgb); rotImg.SelectActiveFrame(e); if (scanParameters[j].WholePage) { parseImage = rotImg.ExtractFrame(e); } else { using (tempImage = rotImg.ExtractFrame(e)) { Rectangle convertedRect = returnConvertedRectangle(tempImage, scanParameters[j].Dimensions); if (convertedRect.IntersectsWith(new Rectangle(0, 0, tempImage.Width, tempImage.Height))) { //GC.Collect(); //Test so I can see what objects are still alive in dump parseImage = tempImage.CopyRectangle(convertedRect); //Exception here } } } } //rotImg.Dispose(); //rotImg = null; if (parseImage != null) { //Now we will apply the image enhancements: if (scanParameters[j].Enhancements != ImageEnhancement.None) { rotImg = EnhanceImage(parseImage, scanParameters[j].Enhancements); parseImage.Dispose(); parseImage = null; } if ((scanParameters[j].BarcodeScanDirection &amp; ScanDirection.LeftToRight) != 0 &amp;&amp; !cancelled) { if (parseImage == null) { tempImage = new gmseBitmap(rotImg.Image, 1); } else { tempImage = new gmseBitmap(parseImage.Image, 1); } bcc = tempImage.ReadBarcodes(param); foreach (gmseBarcodeInfo bc in bcc) { addBarcode(codes, new object[] { searchCount, bc.Text, gmseBarcodeTypeConvert(bc.BarcodeType), scanParameters[j].ZoneName }); } tempImage.Dispose(); tempImage = null; } if ((scanParameters[j].BarcodeScanDirection &amp; ScanDirection.RightToLeft) != 0 &amp;&amp; !cancelled) { if (parseImage == null) { tempImage = new gmseBitmap(rotImg.Image, 1); } else { tempImage = new gmseBitmap(parseImage.Image, 1); } tempImage.RotateFlip(RotateFlipType.Rotate180FlipNone); bcc = tempImage.ReadBarcodes(param); foreach (gmseBarcodeInfo bc in bcc) { addBarcode(codes, new object[] { searchCount, bc.Text, gmseBarcodeTypeConvert(bc.BarcodeType), scanParameters[j].ZoneName }); } tempImage.Dispose(); tempImage = null; } if ((scanParameters[j].BarcodeScanDirection &amp; ScanDirection.TopToBottom) != 0 &amp;&amp; !cancelled) { if (parseImage == null) { tempImage = new gmseBitmap(rotImg.Image, 1); } else { tempImage = new gmseBitmap(parseImage.Image, 1); } tempImage.RotateFlip(RotateFlipType.Rotate90FlipNone); bcc = tempImage.ReadBarcodes(param); foreach (gmseBarcodeInfo bc in bcc) { addBarcode(codes, new object[] { searchCount, bc.Text, gmseBarcodeTypeConvert(bc.BarcodeType), scanParameters[j].ZoneName }); } tempImage.Dispose(); tempImage = null; } if ((scanParameters[j].BarcodeScanDirection &amp; ScanDirection.BottomToTop) != 0 &amp;&amp; !cancelled) { if (parseImage == null) { tempImage = new gmseBitmap(rotImg.Image, 1); } else { tempImage = new gmseBitmap(parseImage.Image, 1); } tempImage.RotateFlip(RotateFlipType.Rotate270FlipNone); bcc = tempImage.ReadBarcodes(param); foreach (gmseBarcodeInfo bc in bcc) { addBarcode(codes, new object[] { searchCount, bc.Text, gmseBarcodeTypeConvert(bc.BarcodeType), scanParameters[j].ZoneName }); } tempImage.Dispose(); tempImage = null; } if (parseImage != null) { parseImage.Dispose(); parseImage = null; } if (rotImg != null) { rotImg.Dispose(); rotImg = null; } } } } searchCount++; if (cancelled) //If cancelled, end the loops { e = framecount; dvCount = files.Length; } } } //end using img //img.Dispose(); //img = null; } } catch (Exception ex) { message = ex.Message; } finally { if (img != null) { img.Dispose(); img = null; } if (rotImg != null) { rotImg.Dispose(); rotImg = null; } if (tempImage != null) { tempImage.Dispose(); tempImage = null; } if (parseImage != null) { parseImage.Dispose(); parseImage = null; } } if (!String.IsNullOrEmpty(message)) throw new Exception(message); return codes; } </code></pre> <p>We use this GMSE Imaging plugin to assist in OCR reading barcodes from scans, it deals with skew by rotating the image by 10 degrees until it gets a read. A bug was discovered where scanning different sized sheets would throw an error.</p> <p>I traced it from our main program to one of our DLLs, where I found it was catching an OutOfMemoryException.</p> <p>The original TIF is 300kb, but there is a fair amount of copying done to rotate the images. (between 4 bitmaps) However I have followed the program through and monitored the locals and it appears that each bitmap is being disposed and assigned null correctly before the method at fault loops.</p> <p>I've also tried adding <code>GC.Collect()</code> at the end of my loop.</p> <p>I am on a 32bit W7 machine, which I have read has 2GB limit per object, with copious amounts of RAM so nothing lacking that that respect. Been watching it on Task Manager and my RAM usage only goes from 1.72GB to 1.78GB.</p> <p>This has been a tricky one to research, as OoM seems to be an unusual occurring error. I was wondering if anyone had any advice in dealing with this kind of exception? I'm not a Visual Studio master, is there an easy way of monitoring resources/memory usage?</p> <p>Or knows of any utilities I can use to assist?</p> <p>Dumping the error message here, not sure how useful the code snippets would be in this situation...</p> <pre><code>System.OutOfMemoryException was caught Message=Out of memory. Source=System.Drawing StackTrace: at System.Drawing.Bitmap.Clone(Rectangle rect, PixelFormat format) at gmse.Imaging.gmseBitmap.CopyRectangle(Rectangle r) at ImagingInterface.ImagingFunctions.ParseBarcodes(String[] files, BarcodeZoneScan[] scanParameters) in C:\Working\Scan.backup\Global Dlls\v2.6.0.02\ScanGlobalDlls\ImagingInterface\ImagingFunctions.cs:line 632 </code></pre> <h2> InnerException:</h2> <p>(currently reading more into GC/Memory management <a href="http://msdn.microsoft.com/en-us/library/ee851764.aspx" rel="nofollow noreferrer">http://msdn.microsoft.com/en-us/library/ee851764.aspx</a> )</p> <p>Working on a <a href="http://msdn.microsoft.com/en-us/library/ee851764.aspx#OOMIsManaged" rel="nofollow noreferrer">step of this guide</a>, using SOS debugger in the Immediate window, with the aim of pinpointing whether the exception is generated from managed or unmanaged code.</p> <hr> <p>Steps from above have indicated it's a problem with the managed code, as exception type from SOS is shown.</p> <pre><code>Exception object: 39594518 Exception type: System.OutOfMemoryException Message: &lt;none&gt; InnerException: &lt;none&gt; StackTrace (generated): </code></pre> <hr> <p><a href="http://pastebin.com/c495M59m" rel="nofollow noreferrer">The Heapdump I took</a> doesn't seem to be thousands of bitmaps like I had kinda expected. Not 100% sure how to interpret the dump so seeing what I can find on it.</p> <p>Not sure where to move from here right now! (searches..)</p> <hr> <p><strong>edit:</strong></p> <p>I have been trying to apply the lessons in <a href="http://blogs.msdn.com/b/tess/archive/2008/02/15/net-debugging-demos-lab-3-memory.aspx" rel="nofollow noreferrer">this blog</a> to my problem.</p> <p><strong>Started with PerfMon</strong></p> <p><img src="https://i.stack.imgur.com/rwTem.png" alt="Perfmon Graph"> This graph shows my program from execution to where it catches the exception.</p> <p>The first two sharp peaks occur after triggering parsing of the scanned image, the last drop off occurs when the exception is caught.</p> <p><img src="https://i.stack.imgur.com/L9nrq.png" alt="Usage Summary"></p> <blockquote> <p>Q: Compare the curves for Virtual Bytes, Private Bytes and #Bytes in all Heaps, do they follow eachother or do they diverge? What is the significance of #Bytes in all heaps diverging from? (As its flat on mine)</p> </blockquote> <p><strong>Examined Memory with !address -summary</strong> MEM_IMAGE corresponded PrivateBytes(113MB) pretty much spot on.</p> <blockquote> <p>Q: Where is most of the memory going (which RegionType)? RegionUsageFree 87.15% RegionUsageIsVAF 5.64% (Busy 43.89%) [memory allocated through VirtualAlloc] RegionUsageImage 5.54% (Busy 43.13%) [Memory that is mapped to a file that is part of an executable image.]</p> </blockquote> <p><strong>In WinDbg with SOS loaded, I did a !DumpHeap</strong></p> <pre><code>//... 7063424c 1201 28824 System.Collections.ArrayList 706228d4 903 28896 System.EventHandler 7062f640 1253 30072 System.RuntimeType 6ec2be78 833 31216 System.Windows.Forms.PropertyStore+IntegerEntry[] 6ec2b0a4 654 34008 System.Windows.Forms.CreateParams 7063547c 318 35472 System.Collections.Hashtable+bucket[] 6ec2aa5c 664 37184 System.Windows.Forms.Control+ControlNativeWindow 70632938 716 40400 System.Int32[] 6c546700 48 49728 System.Data.RBTree`1+Node[[System.Data.DataRow, System.Data]][] 70634944 85 69600 System.Byte[] 6ec2b020 931 85972 System.Windows.Forms.PropertyStore+ObjectEntry[] 6c547758 156 161616 System.Data.RBTree`1+Node[[System.Int32, mscorlib]][] 705e6c28 2107 238912 System.Object[] 00305ce8 18 293480 Free 7062f9ac 5842 301620 System.String Total 35669 objects </code></pre> <p>And here are the top memory hogging objects. I was hoping something would stick out like a sore thumb, like a giant amount of bitmaps or something. Is anything here scream out "I'm acting unusually!" to anyone? (I am trying to examine the top ones individually for suspect things, but would be nice to narrow down the possible culprits a bit more)</p> <p><a href="http://blogs.iis.net/webtopics/archive/2010/04/02/address-summary-explained.aspx" rel="nofollow noreferrer">This page (Address summary explained)</a> has been a big help. However C# is my first language, so I have no prior experience debugging memory issues. Would like to know if I am on the right track (<em>Is GC an issue at all?</em>) as I haven't found anything that's given me any clear indications yet.</p> <hr> <p>Answer: Problem was caused in 3rd party library. Nothing I can do. Found out through deliberation and some tests with stripped down code involving just the method producing the error.</p> <p>Bounty awarded to what I felt I learnt the most from.</p>
    singulars
    1. This table or related slice is empty.
    plurals
    1. This table or related slice is empty.
    1. This table or related slice is empty.
    1. This table or related slice is empty.
 

Querying!

 
Guidance

SQuiL has stopped working due to an internal error.

If you are curious you may find further information in the browser console, which is accessible through the devtools (F12).

Reload