実行時にOutOfMemoryExceptionについて詳細を取得する方法はありますか?または、この例外は、どういうわけか、囲みtry/catchによってキャッチされず、代わりにtryスタック/ catchが呼び出しスタックを上回る可能性がありますか?私はWinDBGを使って再現することができないので、アプリケーションからログできるものでなければなりません。System.Drawing.BitmapのC#OutOfMemoryException
私は長い説明をお詫び申し上げますが、説明するために考えられる原因はたくさんあります。
私はOutofMemoryExceptionのすべての可能性について読んで、基本的にすべてを取り除いています。通常、アプリケーションはうまく動作しますが、時には特定のコンピュータのみで、OutOfMemoryExceptionが発生します。これらのレポートは現場では再現性がないため、私はログを残すだけです。しかし、私はかなりの細部を持っています。
は奇妙な何かである:論理的に近くにメモリを割り当てることがあり
- 何でものtry/catchであるが、例外が未処理として扱われます(とキャッチアップはるかに高いコールスタック)
- StringBuffersが使用されていません
- アプリケーションを再起動して再起動しても例外が発生します。
- 例外はわずか数分後に発生し、約30MiBのメモリしか割り当てられません。チャンクでは1.5MiBを超えません。
- アプリケーション(「任意の」プロセッサ用に構築された)が64ビットとして動作していることを確認しました。
- ディスクスペース(270Gbフリー)とページファイルが不足していません。
- は、LoHフラグメンテーションの問題ではないようです。
これは最近、アプリケーションのさまざまな部分で数回発生しました。初めて、System.Web.Serializationアセンブリを最初にロードするときに例外が発生していたため、.NETアセンブリが破損していると判断しました。そのアセンブリが最初に使用されたメソッド呼び出しの間に起こっていたと判断できました。コンピュータの再イメージング(元のセットアップと同じ)とウィンドウの更新は、この問題を解決しました。
しかし、数日以内に起きる別のクライアント(別のクライアント)も腐敗している可能性は非常に低いです。これは、アセンブリがロードされない場所で発生しています。私は今、最初のエラーを再考しています。私は知っていますか:
- をそれは、スレッドプールのスレッドで起こっている(でSystem.Timers.Timer、[Statthread])
- それは時間Aの周りに起こる(< 5)
- アクティブなスレッドの数が少ないです1MiBファイルがダウンロードされます。これはMemoryStreamに読み込まれるため、2MiBほどの大きさになる可能性があります。これはSystem.Drawing.Bitmapコンストラクタに渡され、ビットマップは約8MiBになります。しかし、それはSystem.Exceptionをキャッチするtry/catchのすべてです。 try/catchに含まれていない唯一のことは、byte []参照を返すことです。この参照は、メモリの割り当てではなく参照コピーでなければなりません。
- この前に他の重要なメモリ割り当ては行われていません。同じように動作するローカルバージョンのヒープを調べると、小さなアイコンヒープ上にあるアプリケーションアイコンと数十のオブジェクトだけが表示されます。
- 特定のシステムで特定の入力を繰り返してもかまいません。しかし、これらのシステムは互いにクローン化されています。明らかな違いは、ウィンドウの更新の順序だけです。
- 実行中のアセンブリに署名があります。それが壊れていないことを保証するチェックサムはありませんか?すべてのシステムアセンブリで同じですか?私は、このインスタンスが破損した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が最初のtry/catchによってキャッチされないだろうが、コールスタックまで、さらにキャッチされるだろう、何らかの理由
And..isを?
あなたはので、バイト配列(データ)のMEM断片化を期待することができます。 DownloadBinaryFileがストリームを返すようにします。データサイズに応じて、MemoryStreamまたはFileStreamを返すように選択できます。 –
スタックトレースを表示できますか?可能性のある回避策については、[https://stackoverflow.com/a/8564247/4684493](https://stackoverflow.com/a/8564247/4684493)を参照してください。また、あなたはおそらく、デバッグ – Hintham
が合意し、最終的に断片化があるかもしれないあなたを助けるために、[MemoryFailPoint](https://msdn.microsoft.com/en-us/library/system.runtime.memoryfailpoint.aspx)を使用することができます。しかし、これは第1または第2の大きなヒープ割り当てで発生しています。 –