Delphi:在PChar指向的字符串变量发生变化后,临时PChar是否保证具有相同的值?

时间:2012-12-29 06:32:41

标签: delphi freepascal

以下代码在我的系统中按预期运行,但在P更改为MyArray[0]后,我不确定procedure Test; var MyArray: array of string; P : PChar; begin SetLength(MyArray, 2); MyArray[0] := 'ABCD'; MyArray[1] := '1234'; // Is P guaranteed to have the same value all the time? P := PChar(MyArray[0]); MyArray[0] := MyArray[1]; MyArray[1] := P; WriteLn(MyArray[0]); WriteLn(MyArray[1]); end; 变量是否有保证具有相同的值一个新的价值。

{{1}}

2 个答案:

答案 0 :(得分:13)

您的代码在技术上无效。由于不应依赖的实现细节,它只会运行。

让我们看一下相关的代码部分:

P := PChar(MyArray[0]);
MyArray[0] := MyArray[1];
MyArray[1] := P;   

首先我们让P指向MyArray [0]的第一个字符。然后我们分配给MyArray [0]。此时,P指向的字符串缓冲区没有理由保持活动状态。没有字符串变量引用它。它的引用计数已经变为零,因此应该取消分配。这使得后续使用P无效。

在哪种情况下,为什么你的代码会运行?因为你使用的字符串恰好是文字。因此它们以等于-1的引用计数存储,并绕过字符串使用的正常堆分配例程。但是如果你要使用不是文字的字符串值,那么我在上面段落中描述的内容就会成功。我希望您的真实代码不使用文字。

所以你的实际问题有点没有实际意义。 P指针只指向一块内存。在您修改指针之前,它仍然指向相同的内存块。如果您修改了内存块的内容,那么如果您取消引用它,P将会看到这些修改。它只是一个像任何其他指针一样的指针。

您需要使用PChar变量。在您的使用中,它是指向编译器管理对象的非托管指针。这提供了很多错误的范围,你陷入了陷阱。如果需要字符串的副本,请将副本复制到另一个字符串变量中。

答案 1 :(得分:2)

似乎从字符串到PChar的类型转换与获取其地址不同。 请参阅下面的代码,它将采用字符串的地址。

procedure Test;
var
  MyArray: array of string;
  P : ^String;

begin
  SetLength(MyArray, 2);
  MyArray[0] := 'ABCD';
  MyArray[1] := '1234';

  // take the pointer
  P := @MyArray[0];

  WriteLn(MyArray[0]);
  WriteLn(MyArray[1]);
  WriteLn(P^);

  // when content of array changes, P^ will change as well
  MyArray[0] := 'HELLO';
  WriteLn(P^);
end;