17

Delphi 中的字符串位于动态内存中。

如何计算string变量使用的实际内存(以字节为单位)?

我知道字符串必须存储一些附加信息,至少是引用计数和长度,但是除了字符之外它使用了多少字节?

var
  S: string;

Delphi 2010, XE, XE2 使用

4

3 回答 3

15

取自 Embarcadero 官方文档的 32 位 UNICODE DELPHI 的布局如下:

UNICODE 德尔福

请注意,在 64 位版本中有一个额外的 longint 字段,用于 16 字节对齐。'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*(Length+1)。对于 32 位或 64 位目标,开销为 12 或 16 个字节。请注意,实际内存块可能比内存管理器确定的需要大。

最后,这个问题有很多错误信息。在 64 位目标上,字符串仍由 32 位有符号整数索引。

于 2012-06-06T08:43:04.387 回答
7

具体来说String,您可以使用SysUtils.ByteLength()获取字符数据的字节长度,如果不为零,则将结果递增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)(如UTF8StringRawByteString, 等,则需要改为使用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 回答