奇怪的StrPCopy()AV错误和解决方法似乎没有意义

时间:2018-01-12 21:43:47

标签: delphi

我遇到了一个处理StrPCopy()的奇怪问题。请查看以下示例代码:

procedure TForm2.butnTestClick(Sender: TObject);
var
  s : string;
begin
  //-- assign string this way will cause AV when trying to StrPCopy()
  s := 'original string';

  //-- assign string this way works!!!!!!!
  //s := Trim('original string');

  //-- AV error when trying to alter the string
  StrPCopy(PChar(s), PChar('changed'));

  //-- should come back with "changed"
  Memo1.Lines.Add(s);
end;

我正在使用Delphi 10 Seattle。如果我试图改变" s"使用StrPCopy()我会得到AV错误。但是,我用Trim()包围我的字符串声明,它会起作用。

似乎通过周围的字符串声明与Trim()触发编译器来关闭对该特定字符串的某种排序优化。我只是不知道那是什么。请帮忙。

2 个答案:

答案 0 :(得分:3)

s引用文字时,它指向只读内存。因此访问违规。

当您使用Trim创建可写字符串时,可以覆盖它而不会出现运行时错误。也就是说,你仍然销毁了字符串,因为空终结符和长度不匹配。

这里的主要问题是将Delphi字符串与空终止的C字符串混合。停止滥用,你的问题就会消失。你根本没有理由打电话给StrPCopy。一旦你停止使用本机Delphi字符串就不会遇到任何此类问题。

编写代码的正确方法如下:

s := 'changed';

答案 1 :(得分:1)

使用StrPCopy()调用是不安全的 - 无论使用通过Trim()赋值创建的新字符串消除了AV。

字符串数据类型比PChar更复杂。它有一个长度组件,它神奇地位于指针和字符数据之前。施放到PChar可以工作,但只能用于阅读。

通过将字符串强制转换为PChar,您可以让StrPCopy爆炸“变形”。字符串到内存的那一部分。在您的示例中,您将以较小的字符串进行复制,因此您可以按内存方式进行复制。结果是一个非常混乱的字符串(长度不匹配字符串,中间有一个空字符),但你在其范围内。

如果您的代码类似......

StrPCopy(PChar(s), PChar('changed to this string'));

...然后你的代码覆盖了字符串的内存占用 - 通常没有立即AV。你可以逃避这一点。你可能没有。