Home Strange StrPCopy() AV error and workaround that does not seems to make sense
Reply: 2

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

Suri M.
1#
Suri M. Published in 2018-01-12 21:43:46Z

I am running into a strange problem dealing with 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. If I try to alter "s" using StrPCopy() I will get AV error. However, I surround my string declaration with Trim(), it will work.

Seems like by surrounding string declaration with Trim() triggers compiler to turn off some sort optimization on that particular string. I just don't know what that is. Please help.

David Heffernan
2#
David Heffernan Reply to 2018-01-12 22:23:40Z

When s refers to a literal it points to read only memory. Hence the access violation.

When you make a writeable string with Trim then it can be overwritten without a runtime error. 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. Stop that abuse and your problems disappear. There is no reason at all for you to call StrPCopy. Once you stop doing that and use native Delphi strings you cannot encounter any such problems.

The correct way to write your code is like so:

s := 'changed';
Aaron Rosenberg
3#
Aaron Rosenberg Reply to 2018-01-16 20:23:09Z

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.

The string datatype is more complex than 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.

By casting the string to a PChar, you are allowing StrPCopy to blast the 'changed' string into that part of memory. 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. You may get away with this. You may not.

You need to login account before you can post.

About| Privacy statement| Terms of Service| Advertising| Contact us| Help| Sitemap|
Processed in 0.325366 second(s) , Gzip On .

© 2016 Powered by mzan.com design MATCHINFO