17

ダイナミックメモリ内にあるDelphiの文字列。

string変数によって使用される実際のメモリ(バイト単位)を計算する方法は?

文字列には、少なくとも参照カウントと長さなどの追加情報を格納する必要があることはわかっていますが、文字を除いて何バイトを使用しますか?

var
  S: string;

Delphi 2010、XE、XE2を使用

4

3 に答える 3

15

Embarcaderoの公式ドキュメントから取得した32ビットUNICODEDELPHIのレイアウトは次のとおりです。

UNICODE DELPHI

16バイトアラインメント用の64ビットバージョンには追加のlongintフィールドがあることに注意してください。'system.pas'のStrRecレコードは次のようになります。

StrRec = packed record
{$IF defined(CPUX64)}
  _Padding: LongInt; // Make 16 byte align for payload..
{$IFEND}
  codePage: Word;
  elemSize: Word;
  refCnt: Longint;
  length: Longint;
end;

ペイロードのサイズは常に2*(長さ+ 1)です。32ビットまたは64ビットのターゲットの場合、オーバーヘッドは12バイトまたは16バイトです。実際のメモリブロックは、メモリマネージャによって決定されるように必要以上に大きくなる可能性があることに注意してください。

最後に、この質問には多くの誤った情報がありました。64ビットターゲットでは、文字列は引き続き32ビットの符号付き整数でインデックス付けされます。

于 2012-06-06T08:43:04.387 に答える
7

String具体的には、を使用SysUtils.ByteLength()して文字データのバイト長を取得できます。ゼロでない場合は、結果を(文字データの前のヘッダー)および(に含まれていないnullターミネータの場合)だけインクリメントしSizeOf(System.StrRec)ますSizeOf(Char)。長さ)、例:

var 
  S: string;
  len: Integer;
begin
  S := ...;
  len := ByteLength(s);
  if len > 0 then Inc(len, SizeOf(StrRec) + SizeOf(Char));
end;

一方、、(など)、などの他の文字列タイプのバイトサイズを計算する場合は、AnsiString代わりAnsiString(N)UTF8String次のRawByteStringように使用する必要があります。System.StringElementSize()

var 
  S: SomeStringType;
  len: Integer;
begin
  S := ...;
  len := Length(S) * StringElementSize(S);
  if len > 0 then Inc(len, SizeOf(StrRec) + StringElementSize(s));
end;

いずれの場合も、文字列に文字が含まれている場合にのみ長さを増やす理由は、空の文字列はメモリをまったく使用せず、nilポインタであるためです。

于 2012-06-06T20:09:51.800 に答える
2

質問に答えるには:

文字列変数によって使用される実際のメモリ(バイト単位)を計算する方法は?

MemSize = Overhead + CharSize * (Length + 1)

CharSize = 1    // for Ansi strings
CharSize = 2    // for Unicode strings
Overhead = 8    // for 32 bit strings
Overhead = 16   // for 64 bit strings
于 2012-06-06T08:51:58.823 に答える