Delphi中的字符串位于动态内存中。
如何计算string
变量使用的实际内存(以字节为单位)?
我知道字符串必须存储一些额外的信息,至少是引用计数和长度,但它除了字符外还使用了多少字节?
var
S: string;
Delphi 2010,XE,XE2使用
答案 0 :(得分:15)
官方Embarcadero文档中的32位UNICODE DELPHI布局如下:
请注意,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 *(长度+ 1)。对于32或64位目标,开销为12或16字节。请注意,实际内存块可能比内存管理器确定的要大。
最后,这个问题有很多错误的信息。在64位目标上,字符串仍然由32位有符号整数索引。
答案 1 :(得分: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)
(例如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
指针。
答案 2 :(得分: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