16

ほとんどの場合、上記のベスト プラクティスに従う傾向があります。

String vs StringBuilderをご覧ください

ただし、使用可能なメモリが十分にある場合でも、 StringBuilder は OutOfMemoryException をスローする可能性があります。「連続したメモリブロック」が必要なため、OOM 例外がスローされます。

参照用のいくつかのリンク StringBuilder OutOfMemoryException

他にもたくさんあります.....

この問題に直面した、または認識している人は何人で、それを解決するために何をしましたか?

不足しているものはありますか?

PS:これは知りませんでした。

私は質問を言い換えました。

*** 同じことが手動連結でも機能しました (これを確認して SO を更新します)。もう 1 つ気になったのは、システムに十分なメモリがあることです。これが、この問題に直面した人がいるかどうか、またはコードに大幅な問題があるかどうかを確認するために、ここでこの質問を提起した理由です。

4

8 に答える 8

19

作成する基になる文字列は、文字の配列として表されるため、連続したメモリ ブロックも必要になります (配列には連続したメモリが必要です)。StringBuilder が OOM 例外をスローした場合、それなしでは基礎となるものを構築することはできません。

文字列を作成すると OOM が発生する場合は、アプリケーションでより深刻な問題が発生している可能性があります。

明確化に応じて編集:

手動連結が成功したときに StringBuilder を使用した文字列の構築が失敗するケースの小さなサブセットがあります。手動連結では、2 つの文字列を結合するために必要な正確な長さが使用されますが、StringBuilder にはメモリを割り当てるための異なるアルゴリズムがあります。これはより積極的であり、文字列に実際に必要なよりも多くのメモリを割り当てる可能性があります。

StringBuilder を使用すると、必要なメモリが一時的に 2 倍になります。これは、文字列が System.String フォームと StringBuilder に短時間同時に存在するためです。

しかし、一方が OOM を引き起こし、もう一方がそうでない場合でも、プログラムのより深刻な問題を示している可能性があります。

于 2008-12-12T18:24:41.553 に答える
4

特定の状況で StringBuilder が OutOfMemoryException をスローする場合、手動で文字列を連結することはより良い解決策ではありません。それははるかに悪いです。これはまさに、StringBuilder が使用されることになっている場合 (非常に長い文字列を作成する場合) です。このサイズの文字列を手動で連結すると、StringBuilder で文字列を作成する場合に必要なメモリの何倍ものメモリが必要になります。

とはいえ、最新のコンピューターでは、文字列が連続したメモリを使い果たしている場合、その設計には深刻な欠陥があります。それほど大きな文字列を作成するために何ができるか想像できません。

于 2008-12-12T18:33:22.957 に答える
3

どのくらいのメモリについて話しているのですか? システムの空きメモリや総メモリについて話しているのではありませんが、連結している文字列の長さはどれくらいですか?

メモリ オーバーフロー例外は、継続的なメモリが利用できないために経験したように、メモリが実際になくなるずっと前に失敗したとしても、ほとんどの場合、コードに関する非常に悪い兆候です。

その時点で、コードを実際に再構築する必要があります。

たとえば、問題に対処するさまざまな方法を次に示します。

  1. 一度に多くのデータをメモリに保持しないでください。ディスクなどに置きます
  2. それを分割し、文字列/文字列ビルダーのリストを保持し、新しいものに切り替える前に特定の長さまで追加するだけで、「連続メモリ」の問題を回避できます
  3. アルゴリズムを再構築して、メモリ内にギガバイトのデータをまったく構築しないようにします
于 2008-12-12T18:50:40.457 に答える
2

実装方法をStringBuilder見ると、実際にStringデータを保持するためにを使用していることがわかります(String内部メソッドがあり、そのStringBuilder場で変更できます)。

つまり、どちらも同じ量のメモリを使用します。ただし、StringBuilderは基になるアレイを自動的に拡張し、必要に応じて必要に応じてコピーします(ただし、容量は2倍になります)。これがメモリ不足エラーの原因である可能性があります。しかし、他の人がすでに指摘しているように、両方ともメモリの連続ブロックが必要です。

于 2008-12-12T19:29:58.317 に答える
2

これが懸念されるほどメモリ制限に近づいている場合は、おそらく別のアーキテクチャを検討するか、より強力なマシンを入手する必要があります。

于 2008-12-12T18:29:49.670 に答える
1

実際の問題は、なぜそんなに長い文字列を扱う必要があるのか​​ということです。この問題に遭遇した場合は、おそらく概念を変更する必要があります。

この問題はSystem.Stringクラスにも影響するため、入力をList< string>にチャンクし、データを並行して処理する必要があります。これにより、適切に記述されていれば全体的なパフォーマンスが向上するはずです。

于 2008-12-12T18:33:08.370 に答える
0

文字列を追加するのと非常によく似た経験をしましたが、String.Formatを追加するのを忘れていました。したがって:

myStringBuilder.Append("1,""{0}""", someVeryLargeIntVariable)

になるはずだった:

myStringBuilder.Append(String.Format("1,""{0}""", someVeryLargeIntVariable))

これは失敗した私のvb.netコードであることに注意してください。私はc#で同様のテストを次のように複製しました:

myStringBuilder.Append('a', 1564544656);

対。

myStringBuilder.Append(string.Format("1,\"{0}\"", 1564544656));

しかし、私の場合、vb.netは暗黙の変換のb / cで問題を引き起こしました(c#でまったく同じ問題を並行させることはできませんでした)。

それが誰かに役立つことを願っています。

于 2011-12-22T21:32:00.900 に答える
0

さまざまな stringbuilder で連続して作成された非常に大きな文字列でこの例外が発生し (匿名関数内で宣言されていたため、問題は発生しなかったはずです)、最終的に匿名関数の外部で宣言された単一の StringBuilder を再利用することで解決しました。

于 2011-09-17T22:27:31.403 に答える