Delphi string内存结构


本文整理自网络,侵删。

 
var
  s: AnsiString;
begin
  s := '1234567890';
  showmessage(s);
end;

变量s的内存结构为
A8 03 01 00 FF FF FF FF 0A 00 00 00 31 32 33 34 35 36 37 38 39 30 00

01~02 字节是代码页,如上面的0x03A8为十进制的936,表示简体中文GBK
03~04 字节表示每个字符所占的字节数(ANSI为1,Unicode为2)
05~08 字节是该字符串的引用计数
09~12 字节是该字符串的字符个数
13~?? 字节就是字符串实际的内容了
??    最后一个字节是00,字符串的结束符


对于string变量类型s,它实际上是一个指针,指向字符串首个字符的地址,也就是第13个字节

这里需要注意的是,在Delphi 2009以前的版本中是没有描述代码页的4字节的,而是直接从第05字节开始。

上面的字符串引用计数为什么会是0xFFFFFFFF呢?因为该字符串是常量,对于常量字符串,引用计数总是-1
若有N处相同的字符串常量时,就有N份的拷贝,这样就造成了空间上的浪费,Delphi并未作出优化
下面的代码就可以说明问题,两次显示的字符串内存地址不同。

procedure Foo();
var
  s: AnsiString;
begin
  s := '1234567890';
  ShowMessage(IntToHex(Integer(@s[1]), 8));
end;
 
procedure TForm1.Button1Click(Sender: TObject);
var
  s: AnsiString;
begin
  s := '1234567890';
  ShowMessage(IntToHex(Integer(@s[1]), 8));
  Foo;
end;
接着看看下面的代码

var
  s: AnsiString;
begin
  s := Caption;
  ShowMessage(IntToHex(Integer(@s[1]), 8));
end;
由于没有使用常量字符串,所以引用计数不再是-1
A8 03 01 00 01 00 00 00 05 00 00 00 46 6F 72 6D 31 00

在知道了string的内存结构后,我们就可以通过代码来观测引用计数的值了

var
  s, s2: AnsiString;
  p: ^Integer;
begin
  s := Caption;
  p := Pointer(@s[1]);
  Dec(p, 2);
  ShowMessage(IntToStr(p^));  // 1
 
  s2 := s;                    // 引用计数+1了
  ShowMessage(IntToStr(p^));  // 2
end;

――――――――――――――――

原文链接:https://blog.csdn.net/aqtata/article/details/38905387

相关阅读 >>

Delphi injectmemexe

Delphi 创建dll文件 及其调用和注意事项

Delphi 试试带参数的 exit

Delphi application.title在win7下失效了?

Delphi 禁止窗口移动

Delphi常用日期函数

Delphi 获取url特殊路径

Delphi 在运行时改变控件的大小

Delphi 相对路径和绝对路径的转换

Delphi kbmmw sampleservice/sampleclient方式传输数据集

更多相关阅读请进入《Delphi》频道 >>



打赏

取消

感谢您的支持,我会继续努力的!

扫码支持
扫码打赏,您说多少就多少

打开支付宝扫一扫,即可进行扫码打赏哦

分享从这里开始,精彩与您同在

评论

管理员已关闭评论功能...