質問: VB.netでのWindowsアプリケーション開発をしています。 String文字列の連結においてOutOfMemoryExceptionのエラーがスローされます。 手法としてはSingleの数値をカンマで区切り、1000個のカンマ区切り文字列を作成します。 その文字列は「temp_Str as String」の変数に格納していくのですが、 大型のループ処理で10万件以上作成されたところで上記のエラーが発生します。 (時間にして2~3時間程度経過した時点) 少なくとも数100万件の処理を行いたいのですが、 うまくメモリー管理をする方法はないでしょうか? 今現在GC.CollectやRemove等の処理は入れているのですが、あまり効果がありません。 よろしくお願いいたします。
回答: yhataさんの指摘も踏まえて回答を改めます。 String結合を無制限に繰り返すことが原因で`OutOfMemoryException`が発生する場合ですが、例外が表しているようにメモリ不足の可能性があります。32bitアプリケーションでは2GBのメモリを使用できますが、その全てがデータに使えるわけではないため、それよりも少ない使用量でも`OutOfMemoryException`が発生します。 `String`の代わりに`StringBuilder`を使用することで処理速度は向上しますが、処理可能なデータ量はほぼほぼ改善されません。結局、処理方法を抜本的に見直す必要があります。少なくともString結合を無制限に繰り返すことはできません。 必然的にString結合はある程度、少量に抑えられることになるはずですが、その際に作成される文字列が約4万文字以下に抑えられるのであればString結合と`StringBuilder`とにメモリ上の優劣はありません。(4万文字の根拠は、.NETにおいてオブジェクトサイズが85KB未満・以上とで管理方法が異なることに起因します。) 例えば今回であれば、全件を一気に処理せず1件ずつ処理するように見直した方がいいかもしれません。その場合、1件のデータは > > Singleの数値をカンマで区切り、1000個のカンマ区切り文字列 > > > とのことですが、この程度であれば最悪ケースでも1万文字程度に収まります。 `StringBuilder`はyhataさんが説明されているように大きな文字列を作成しても85KB未満に収まるように分割管理されているため文字列編集のパフォーマンスに優れます。ただし、これは.NET 4にて改善されたもので、.NET 3.5以前では享受できませんので気を付ける必要があります。その場合どうすべきかというと、予め文字列長を見積もり、`StringBuilder.Capacity`プロパティを設定することです。これにより事前にメモリ確保をし、文字列編集時の逐次メモリ拡張を排除できます。