4

私のプロジェクトでは、「メモリ不足の例外」という文字列に問題があり、MM は使用されていません。問題は、文字列の長さが 2 300,000 シンボルになると表示されます。十分なメモリがあり、コードの同じ部分で 100,000,000 文字の文字列を作成できるという事実にもかかわらず。

Google は役に立ちませんでした。逆アセンブルできません (スキルがありません)。そのため、2 000 000 000 シンボル未満の文字列でメモリ不足の例外を取得できる最小限のテスト例を作成することにしました。そのような例を作成することはできませんでしたが、奇妙なものを作成しました:

program Project2;
{$APPTYPE CONSOLE}
uses
   SysUtils;

var s : string;
    k : integer;

function b : string;
begin
 result := 'f';
end;

procedure c;
var ss : string;
begin
  s := s + '{' +  b + '}';
  ss :=  'a';

  if k mod 100001 = 0 then
  begin
     // ss[1] := 'd';    // uncoment me
     write(k mod 10);
  end;

  inc(k);
end;

begin
  while true do c;
end.

このコードは正常に動作します。いくつかの追加操作でグローバル文字列に何かを追加するだけです。問題は、マークされた文字列のコメントを外すと、(最適化の有無にかかわらず) 大幅に遅くなるということです。この代入値が 100,001 回の反復に 1 回であることを考えると、速度が低下してはなりません。

質問:

  1. Delphi のデフォルト文字列はどのように機能しますか?

  2. 速度低下を避けるには?

  3. メモリ不足を回避するには?

PS メイン プロジェクトに FastMM を含めると、エラーは消えます pps 文字列のコメントを外した例では、Windows 7 を 3 分で BSOD に送信します (ユーザー モードから)。

4

2 に答える 2

9

実行による文字列の割り当て

s := s + '{' +  b + '}';

長時間実行されるループでは、単にメモリが断片化されます。文字列に十分なメモリがあるかもしれませんが、それだけでは十分ではありません。メモリが連続している必要がありますが、割り当てパターンではそれが難しくなります。

を呼び出して、文字列を最終的に必要な長さに事前に割り当てて、問題を解決しますSetLength

于 2012-04-12T11:13:14.967 に答える
4

1. Delphi のデフォルト文字列はどのように機能しますか?

string( 経由で) 影響を受けるたびに、新しいが割り当てられます:=

あれは、

s := s + '{' +  b + '}';

stringforを割り当て、s + '{' + b + '}';それを variable にコピーしますs

この行を実行するたびに、1 つのメモリ割り当てと 1 つのメモリ解放が行われます。FastMM4を使用しても、これは遅くなる可能性があります。しかし、古い MM では、非常に遅くなる可能性があります。

2.スローダウンを避けるには?

古い Delphi を使用している場合、「Borland」メモリ マネージャを使用すると、割り当てと再割り当てが非常に遅くなります。そして、それは記憶を大幅に断片化します。

このss[1] := 'd'メモリの断片化と、Borland Memory Manager がこの行のメモリ割り当てのために遅いクリーンアップを行わなければならないという事実により、 は確かに非常に遅くなります。

次のように行を変更します。

var ss: string[1];

shortstringまた、スタックに割り当てられ、ヒープが使用されないため、速度が低下することはありません。

したがって、速度低下を避けるために:

  • FastMM4などの最新のメモリ マネージャーを使用します。
  • TStringBuilderようなクラス、またはTMemoryStreamデータを追加する古き良きクラスを使用します。メモリの再割り当てがはるかに少なくなるため、はるかに高速になります。

3. メモリ不足を回避するには?

メモリ不足エラーは、メモリの断片化が原因です。

したがって、前の質問の 2 つの解決策でこれが解決されます。

于 2012-04-12T13:34:05.437 に答える