ダイナミックメモリ内にあるDelphiの文字列。
string
変数によって使用される実際のメモリ(バイト単位)を計算する方法は?
文字列には、少なくとも参照カウントと長さなどの追加情報を格納する必要があることはわかっていますが、文字を除いて何バイトを使用しますか?
var
S: string;
Delphi 2010、XE、XE2を使用
Embarcaderoの公式ドキュメントから取得した32ビットUNICODEDELPHIのレイアウトは次のとおりです。
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ビットの符号付き整数でインデックス付けされます。
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
ポインタであるためです。
質問に答えるには:
文字列変数によって使用される実際のメモリ(バイト単位)を計算する方法は?
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