The following code runs as expected in my system, but I'm not sure whether the P
variable is guaranteed to have the same value after MyArray[0]
is changed to a 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;
Your code is technically invalid. It only runs at all due to an implementation detail that should not be relied upon.
Let's take a look at the pertinent section of code:
P := PChar(MyArray[0]);
MyArray[0] := MyArray[1];
MyArray[1] := P;
First we make P point to the first character of MyArray[0]. Then we assign to MyArray[0]. At this point there's no reason for the string buffer that P points at to be kept alive. No string variable refers to it. Its reference count has gone to zero, and so it should be deallocated. Which makes the subsequent use of P invalid.
In which case, why does your code run? Because the strings you use happen to be literals. And so they are stored with reference count equal to -1 and bypass the normal heap allocation routines used by strings. But if you were to use string values that were not literals, then what I describe in the paragraph above would come to pass. And I expect that your real code doesn't use literals.
So your actual question is somewhat moot. The P pointer just points at a block of memory. It remains pointing at the same block of memory until you modify the pointer. If you modify the contents of the block of memory, then P will see those modifications if you de-reference it. It's just a pointer like any other pointer.
You need to take care using a PChar variable. In your use, it is an unmanaged pointer into a compiler managed object. That provides lots of scope for errors and you've fallen into the trap. If you want a copy of a string, take a copy into another string variable.
It seems that type casting from a string to PChar is different than taking its address. See the code below, it will take the address of 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;
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With