C # OutOfMemoryException in System.Drawing.Bitmap

Is there a way to get more details at runtime of an OutOfMemoryException? Or, can this exception somehow not be caught by the try / catch application and instead try / catch the above call stack? I can not play using WinDBG, so I have to register in the application.

I apologize for the long explanation, but there are many possible reasons that I explain.

I read all of the OutofMemoryException exception options and basically eliminated all of them. Usually the application works fine, but sometimes on only certain computers, I get an OutOfMemoryException. Since these reports are in a field that cannot be played locally, I only have logs. But I have quite a few details.

What is strange:

  • Everything that can logically allocate memory in close proximity is in try / catch, but the exception is treated as unhandled (and falls well above the call stack).
  • No StringBuffers Used
  • An exception occurs even after rebooting and restarting the application.
  • An exception occurs only after a couple of minutes and only about 30 megabytes of memory is allocated in pieces of no more than 1.5 MB.
  • The tested application (built for "any" processor) works like 64 bits.
  • There is no lack of disk space (270Gb for free) and a swap file.
  • not a possible problem of LoH fragmentation.

. , .NET, , System.Web.Serialization. , , . ( ) .

, , , , . , . . :

  • (System.Timers.Timer, [Statthread])
  • (< 5)
  • , 1MiB . MemoryStream, 2MiB. System.Drawing.Bitmap, , 8MiB. , try/catch, System.Exception. , try/catch, byte [], , .
  • . , , , Small Object.
  • . . .
  • , , . , , ? ? , dll .
  • . , .
  • COM-. , , , 20 COM- (IUPnPDevice)

    // Stack Trace indicates this method is throwing the OutOfMemoryException
    // It isn't CAUGHT here, though, so not in the try/catch.
    //
    internal void Render(int w, int h)
    {
        if (bitmap != null)
        {
            bitmap.Dispose();
            bitmap = null;
        }
    
        if (!String.IsNullOrEmpty(url))
        {
        // this information is printed successfully to log, with correct url
        // exception occurs sometime AFTER this somehow.
            Logger.Default.LogInfo("Loading {0}", url);
    
        // when file contents changed (to go from 1MiB to 500MiB, the error went away)
            byte[] data = DownloadBinaryFile(url);
            if (data != null)
            {
                try
                {
                    Bitmap bmp;
                    using (var ms = new MemoryStream(data))
                    {
                        bmp = new Bitmap(ms);
                    }
                    bitmap = bmp;
                }
                catch (Exception)
                {
                    // We do not catch anything here.
                    Logger.Default.LogWarning("WARNING: Exception loading image {0}", url);
                }
            }
    
            //
            // if we had any errors, just skip this slide
            //
            if (bitmap == null)
            {
                return;
            }
    
            // QUESTION EDIT:
            // in the problematic version, there was actually an unnecessary
            // call here that turns out to be where the exception was raised:
            using( Graphics g = Graphics.FromImage(bitmap)) {
            }
    
        }
    }
    
    // calling this would trigger loading of the System.Web assembly, except
    // similar method has been called earlier that read everything. Only
    // class being used first time is the BinaryReader, which is in System.IO 
    // and already loaded.
    internal static byte[] DownloadBinaryFile(String strURL, int timeout = 30000)
    {
        try
        {
            HttpWebRequest myWebRequest = HttpWebRequest.Create(strURL) as HttpWebRequest;
    
            myWebRequest.KeepAlive = true;
            myWebRequest.Timeout = timeout;
            myWebRequest.ReadWriteTimeout = timeout;
            myWebRequest.UserAgent = "Mozilla/4.0 (compatible; MSIE 5.01; Windows NT 5.0)";
    
            Encoding encode = System.Text.Encoding.GetEncoding("utf-8");
    
            using (HttpWebResponse myWebResponse = myWebRequest.GetResponse() as HttpWebResponse)
            {
                if (myWebResponse.StatusCode != HttpStatusCode.OK)
                {
                    Logger.Default.LogWarning("WARNING: Response {0} loading {1}", myWebResponse.StatusCode, strURL);
                    return null;
                }
    
                using (Stream receiveStream = myWebResponse.GetResponseStream())
                {
                    using (BinaryReader readStream = new BinaryReader(receiveStream))
                    {
                        // this extension method uses MemoryStream, but seems irrelevant since we don't catch anything here.
                        return readStream.ReadAllBytes();
                    }
                }
            }
        }
        catch (Exception e)
        {
            // we do not catch anything here.
            Logger.Default.LogError("ERROR: Exception {0} loading {1}", e.Message, strURL);
        }
        return null;
    }
    

, , . - OutOfMemoryException, , , , ?

.. - , OutOfMemoryException /catch, ?

+4
1

. , , - . :

            Bitmap bmp;
            using (var ms = new MemoryStream(data))
            {
                bmp = new Bitmap(ms);
            }
            bitmap = bmp;

Bitmap :

Bitmap.

, MemoryStream . , Bitmap, -, . (EDIT: , , 1MiB, FromStream JPEG. JPEG < 1MiB . JPEG 1MiB, )

, Microsoft . , , ( http-), , , :

// Create a Bitmap object from a file.
using (var ms = new MemoryStream(data))
{
   bmp = new Bitmap(ms);
   Rectangle cloneRect = new Rectangle(0, 0, bmp.Width, bmp.Height);
   System.Drawing.Imaging.PixelFormat format = bmp.PixelFormat;
   this.bitmap = bmp.Clone(cloneRect, bmp.PixelFormat);    
}

, , , , , . Graphics.FromImage() , . , .

+4

Source: https://habr.com/ru/post/1687697/


All Articles