8

これは Delphi 2009 であるため、Unicode が適用されます。

次のように、バッファから StringList に文字列をロードするコードがいくつかありました。

      var Buffer: TBytes; RecStart, RecEnd: PChar; S: string;

      FileStream.Read(Buffer[0], Size);

      repeat
         ... find next record RecStart and RecEnd that point into the buffer;        

         SetString(S, RecStart, RecEnd - RecStart);
         MyStringList.Add(S);
      until end of buffer

しかし、いくつかの変更中に、ロジックを変更して、最終的に同じレコードを追加することになりましたが、SetString を介してではなく、個別に派生した文字列として、つまり

      var SRecord: string;

      repeat
        SRecord := '';
        repeat
          SRecord := SRecord + ... processed line from the buffer;
        until end of record in the buffer

        MyStringList.Add(SRecord);
      until end of buffer

私が気付いたのは、StringList のメモリ使用量が 52 MB から約 70 MB に増加したことです。それは30%以上の増加でした。

メモリ使用量を元に戻すには、次のように SetString を使用して文字列変数を作成し、StringList に追加する必要があることがわかりました。

      repeat
        SRecord := '';
        repeat
          SRecord := SRecord + ... processed line from the buffer;
        until end of record in the buffer

        SetString(S, PChar(SRecord), length(SRecord));
        MyStringList.Add(S);
      until end of buffer

S と SRecord を調べて比較すると、すべてのケースでまったく同じです。ただし、SRecord を MyStringList に追加すると、S を追加するよりも多くのメモリが使用されます。

何が起こっているのか、なぜ SetString がメモリを節約するのか知っている人はいますか?


ファローアップ。まさかとは思いましたが、念のため確認してみました。

ない:

  SetLength(SRecord, length(SRecord));

または

  Trim(SRecord);

余分なスペースを解放します。そのためには SetString が必要なようです。

4

2 に答える 2

15

文字列を連結する場合、メモリ マネージャーはより多くのメモリを割り当てます。これは、文字列をさらに追加することを想定し、将来の連結のために追加のスペースを割り当てるためです。このように、文字列の割り当てサイズは、使用されるサイズよりもはるかに大きくなります (使用されるメモリ マネージャーによって異なります)。SetString を使用すると、新しい文字列の割り当てサイズは、使用したサイズとほぼ同じになります。そして、SRecord 文字列が範囲外になり、その参照カウントがゼロになると、SRecord によって占有されていたメモリが解放されます。したがって、文字列に必要な最小の割り当てサイズになります。

于 2010-09-25T20:00:52.640 に答える
-1

GetMem/FreeMem へのすべての呼び出しをデフォルトのメモリ マネージャーに渡すメモリ マネージャー フィルター (Get/SetMemoryManager) のインストールを試みますが、統計情報収集も実行します。おそらく、両方のバリアントのメモリ消費量が同じであることがわかります。

それは単なるメモリの断片化です。

于 2010-09-26T08:26:58.300 に答える