简体   繁体   English

奇怪的StrPCopy()AV错误和变通办法似乎没有意义

[英]Strange StrPCopy() AV error and workaround that does not seems to make sense

I am running into a strange problem dealing with StrPCopy(). 我在处理StrPCopy()时遇到一个奇怪的问题。 Please take a look at the sample codes below: 请查看以下示例代码:

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;

I am using Delphi 10 Seattle. 我正在使用Delphi 10 Seattle。 If I try to alter "s" using StrPCopy() I will get AV error. 如果尝试使用StrPCopy()更改“ s”,则会出现AV错误。 However, I surround my string declaration with Trim(), it will work. 但是,我用Trim()包围了字符串声明,它将起作用。

Seems like by surrounding string declaration with Trim() triggers compiler to turn off some sort optimization on that particular string. 好像用Trim()将字符串声明括起来一样,会触发编译器关闭对该特定字符串的某种排序优化。 I just don't know what that is. 我只是不知道那是什么。 Please help. 请帮忙。

When s refers to a literal it points to read only memory. s引用文字时,它指向只读存储器。 Hence the access violation. 因此,访问冲突。

When you make a writeable string with Trim then it can be overwritten without a runtime error. 使用Trim编写可写字符串时,可以将其覆盖而不会出现运行时错误。 That said, you've still destroyed the string because the null terminator and the length don't match. 也就是说,由于空终止符和长度不匹配,您仍然破坏了字符串。

Your main problem here is the mixing of Delphi strings with null terminated C strings. 您的主要问题是将Delphi字符串与以N结尾的C字符串混合。 Stop that abuse and your problems disappear. 停止这种虐待,您的问题就会消失。 There is no reason at all for you to call StrPCopy . 根本没有理由调用StrPCopy Once you stop doing that and use native Delphi strings you cannot encounter any such problems. 一旦停止这样做并使用本机Delphi字符串,就不会遇到任何此类问题。

The correct way to write your code is like so: 编写代码的正确方法如下:

s := 'changed';

Your usage of StrPCopy() call is not safe - regardless of the AV that is eliminated with the use of the new string that is created with the Trim() assignment. 您使用StrPCopy()调用并不安全-不管使用通过Trim()分配创建的新字符串消除了AV还是什么。

The string datatype is more complex than PChar. 字符串数据类型比PChar更复杂。 It has a length component that magically sits ahead of the pointer and the character data. 它具有一个长度组成部分,神奇地位于指针和字符数据的前面。 Casting to a PChar works, but should only be used for reading. 强制转换为PChar可以,但是只能用于阅读。

By casting the string to a PChar, you are allowing StrPCopy to blast the 'changed' string into that part of memory. 通过将字符串强制转换为PChar,可以让StrPCopy将“已更改”的字符串放入内存的该部分。 In your example, you're copying in a smaller string, so you're OK memory-wise. 在您的示例中,您正在复制一个较小的字符串,因此您可以明智地使用内存。 The result is a very confused string (length doesn't match the string, there's a null character in the middle), but you're within it's bounds. 结果是一个非常混乱的字符串(长度与字符串不匹配,中间有一个空字符),但是您在它的范围之内。

If your code was something like... 如果您的代码是类似...

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

... then your code is overwriting past the string's memory footprint - usually without an immediate AV. ...那么您的代码将覆盖字符串的内存占用量以上-通常没有立即的AV。 You may get away with this. 您可能会摆脱这个。 You may not. 你不可以。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM