5

我试图了解指向字符串的指针是如何工作的。我有一个代码(不完全是原创的),是有人写的,这个人已经不在了,所以我需要了解这种用法​​的想法。

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指针会分配一个空字符串,对吗?分配后,我尝试查看指针指向的字符串的引用计数/长度,PChar(@pStr^[1])[-8]但它返回无意义(14),并且长度字节也是错误的。

此外,问题是,使用指针通过 Windows 消息传递字符串是否安全?

4

1 回答 1

8

New(pStr)在堆上分配 astring并返回指向它的指针。因为string是托管类型,所以字符串默认初始化为空字符串。由于 astring被实现为指针,因此您基本上拥有的是指向指针的指针。

您的代码非常好,只要您只将消息发布到您自己的进程。由于消息的有效负载是一个指针,它只意味着在您的进程的虚拟地址空间的上下文中。如果你想发送到不同的进程,你需要一个 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
于 2013-10-22T08:16:16.090 回答