- PR -

OutOfMemoryExceptionの対策について

投稿者投稿内容
きくちゃん
ぬし
会議室デビュー日: 2003/08/01
投稿数: 854
お住まい・勤務地: 都内某所
投稿日時: 2006-05-16 20:22
Draさん、こんばんは。

ReadLine メソッドの解説には、以下のような文章があります。

引用:

現在のメソッドが OutOfMemoryException をスローした場合、
(途中略)
このような状況を回避し、信頼性の高いコードを作成するには、Read メソッドを使用して、割り当て済みのバッファに読み取った文字を格納する必要があります。


わざわざ解説されているって事は、何かの加減で、割と頻繁に発生する可能性があるって事なんでしょうかねぇ。

あと、重箱の隅を突くようですが、

引用:

If strLine = Nothing Then


これは
If strLine Is Nothing Then
にしないと、常に Else の方へ流れませんでしたっけ?

それと、

引用:

Catch ex As Exception
Return false
End Try


StreamReader とか StreamWriter とかは、Finally で Close すべきですね。
Dra
大ベテラン
会議室デビュー日: 2004/10/04
投稿数: 111
投稿日時: 2006-05-16 21:43
うにくまさん・きくちゃんさん、ありがとうございます。

>If strLine Is Nothing Then
>StreamReader とか StreamWriter とかは、Finally で Close すべきですね。
ご指摘ありがとうございます。

ReadLine メソッドの解説にあてはまりそうですね。レコード毎にbyte数が異なる為
Readメソッドの使用は難しいと考えられます。(ある項目をみて書込みを判断する)が検討してみます。
ありがとうございます。
渋木宏明(ひどり)
ぬし
会議室デビュー日: 2004/01/14
投稿数: 1155
お住まい・勤務地: 東京
投稿日時: 2006-05-16 22:56
引用:

ちなみに追いつく追いつかないとはどういう意味なのでしょうか?
GC中は他スレッドは停止すると認識してるんですが・・・



いいえ。.NET は GC 専任のスレッドがバックグラウンドでヒープのお掃除をします。

遠い昔に GDNJ で議論になりましたが

for(long i = 0; i < 1000000; i++)
{
byte[] buffer = new byte [256 * 1024 * 1024];
}

みたいなコードは、少なくとも .NET 1.x では OutOfMemoryException がスローされます。
Jitta
ぬし
会議室デビュー日: 2002/07/05
投稿数: 6267
お住まい・勤務地: 兵庫県・海手
投稿日時: 2006-05-16 23:07
引用:

うにくまさんの書き込み (2006-05-16 17:45) より:
StreamReader/StreamWriterのバッファは指定しない限り、
1024+4096byte以上使用されることはなく適宜Flushされます。
明示的にFlushされるまですべてを保持しているわけではありません。
なので、これらのクラスが原因とは考えにくいです。

試しに4GBのファイルを作成し、Read/ReadLine,Write/WriteLineを
色々と組み合わせてみましたが、読み書き共に問題なく動作しました。

例外情報を編集せずに提示してみては?


 私も、ディスクの空き領域の関係で 2GB ですが、全く問題ありませんでした。タスクマネージャの報告によると、プロセスが使用するメモリは常に一定でした。なので、Stream 系の問題とは考えにくいです。

 うにくまさんも指摘されているとおり、Exception.ToString() の値を、そのまま書き出してください。2日が過ぎようとしていますが、Read でエラーになることと、Exception.ToString() の値とを最初に出していれば、もっと早くに解決したように思います。


 また、

If 条件(str1 = "1") Then

のところも、文法的におかしいので、いろいろな処理を省略しているのだと思います。そこに本当の問題があるようにも思います。
うにくま
ベテラン
会議室デビュー日: 2005/11/05
投稿数: 82
投稿日時: 2006-05-17 03:36
引用:

コード:
for(long i = 0; i < 1000000; i++) 
{
    byte[] buffer = new byte [256 * 1024 * 1024];
}


みたいなコードは、少なくとも .NET 1.x では OutOfMemoryException がスローされます。


ですが、これはnewobj/newarrで(Large Objectの場合だけ?)適切にCollectされていなかった
の方が自分としてはしっくりくるのですが。。。
まぁ、確認のしようがないんですけどね。


AutoFlushプロパティについてですが、
これは書き込みが既定バッファに満たなくてもFlushするかどうかという事だと思います。
たとえば、1100byteが書き込み(Write)されたとして、
Falseの場合は、1024byte (StreamWriterのバッファ -> FileStreamのバッファ)
Trueの場合は、1100byte (StreamWriterのバッファ -> FileStreamのバッファ -> デバイス)
がFlushされるということだと思います。それと処理も微妙に違います。
Dra
大ベテラン
会議室デビュー日: 2004/10/04
投稿数: 111
投稿日時: 2006-05-17 09:15
みなさんありがとうございます。
現状は以下のように書込みなしの場合でも同様なエラーが発生し、解決しておりません。
エラーに関しては、「種類 System.OutOfMemoryException の例外がスローされました。」
のみしかとれません。

Dim strLine As String = ""
Dim srFile As New System.IO.StreamReader("読込みファイル", System.Text.Encoding.Default)
Dim sw As New System.IO.StreamWriter("書込みファイル", False, System.Text.Encoding.GetEncoding(932))
Try
While Not strLine Is Nothing
strLine = Nothing
'1行ずつ読み込む
strLine = srFile.ReadLine()
If strLine Is Nothing Then
'何も読み込まない時はWhile分を抜ける
Exit While
Else
'書込みはなし
End If
End While
Return true
Catch ex As Exception
Return false
Finally
srFile.Close()
sw.Close()
End Try
ぶさいくろう
ぬし
会議室デビュー日: 2005/11/22
投稿数: 1232
お住まい・勤務地: 川崎市(は俺も含めてロクな人間が住んでないよw)
投稿日時: 2006-05-17 09:41
strLineってのをWhile内で宣言してもダメかいな?
GCの手助けにはなるだろう。(ってNothingと効果は同じだろうが)
じゃんぬねっと
ぬし
会議室デビュー日: 2004/12/22
投稿数: 7811
お住まい・勤務地: 愛知県名古屋市
投稿日時: 2006-05-17 09:48
私も 300MB ほどのファイルを作成し同様の実装をしてみましたが、正常に動作しました。
やはりファイル自体か、その他の実装による影響を疑った方が良いのではないでしょうか?

unibon さんが、「問題の切り分け」の仕方を提示してくださっていますが、すべて試されていますか?

_________________
C# と VB.NET の入門サイト
じゃんぬねっと日誌

スキルアップ/キャリアアップ(JOB@IT)