Delphi: Is temporary PChar guaranteed to have the same value after changing the string variable designated by PChar?

The following code works as expected on my system, but I'm not sure if the P variable is guaranteed to have the same value after MyArray[0] is changed to the new value.

 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; 
+6
source share
2 answers

Your code is technically invalid. It only works because of implementation details you cannot rely on.

Let's look at the corresponding section of code:

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

First we make P the point of the first character MyArray [0]. Then we assign MyArray [0]. There is currently no reason for the string buffer at which point P remains alive. No string variable refers to it. His countdown has gone to zero, and therefore he must be freed. This makes subsequent use of P invalid.

In this case, why does your code work? Because the strings you use are literals. And therefore, they are stored with a number of links equal to -1, and bypass the usual heap allocation routines used by strings. But if you used string values ​​that were not literals, then what I described in the paragraph above would have come true. And I expect your real code does not use literals.

So, your actual question is somewhat controversial. Pointer P simply points to a block of memory. It remains to point to the same block of memory until you change the pointer. If you change the contents of the memory block, then P will see these changes if you cancel the link to it. It is just a pointer like any other pointer.

You need to take care using the PChar variable. In your use, this is an unmanaged pointer to an object controlled by the compiler. This gives you plenty of room for error, and you are trapped. If you need a copy of a string, take a copy to another string variable.

+13
source

It seems that dropping the type from the string in PChar is different from the fact that it takes its address. See the code below, it will take the address of the string.

 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; 
+2
source

All Articles