我试图了解指向字符串的指针是如何工作的。我有一个代码(不完全是原创的),这是由某人写的,而且这个人不在这里,所以我需要理解这种用法的想法。
var
STR: string;
pStr: ^string;
begin
STR := 'Hello world';
New(pStr);
pStr^ := STR;
PostMessage(Handle, WM_USER+1, wParam(pStr), 0);
end;
现在我肯定知道,消息处理程序获取消息并且指针包含可以使用的字符串,但是这些操作的“幕后”会发生什么??
我试图做一个小项目。我认为,将字符串分配给str指针指向的字符串实际上会增加原始字符串的refcount并且不会创建字符串的任何副本,但refcount保持为1并且它似乎确实复制了内容。
所以得到问题,发生了什么?在指针上调用New
会分配一个空字符串,对吧?
在赋值之后,我试着查看一个字符串的refcount / length,指针指向这个PChar(@pStr^[1])[-8]
,但是它返回了废话(14),长度字节也是错误的。
另外问题是,使用指针以这种方式通过Windows消息传递字符串是否安全?
答案 0 :(得分:8)
New(pStr)
在堆上分配string
并返回指向它的指针。由于string
是托管类型,因此字符串默认初始化为空字符串。由于string
被实现为指针,因此您从根本上拥有指向指针的指针。
只要您将邮件发布到您自己的流程,您的代码就完全没问题了。由于消息的有效负载是指针,因此它仅表示进程的虚拟地址空间的上下文中的某些内容。如果你想发送到另一个进程,你需要一个IPC机制。
显然,在将消息从队列中拉出的代码中,您需要处理该字符串。像这样:
var
p: ^string;
str: string;
....
p := Pointer(wParam);
str := p^;
Dispose(p);
您查询引用计数和长度的代码是错误的。以下是如何正确执行此操作:
{$APPTYPE CONSOLE}
var
pStr: ^string;
p: PInteger;
begin
New(pStr);
pStr^ := 'Hello world';
p := PInteger(pStr^);
dec(p);
Writeln(p^); // length
dec(p);
Writeln(p^); // ref count
Readln;
end.
<强>输出:强>
11 1