Another possible mistake from your original post:
pstr:=@str;
This may not may not give you a pointer to the chars in the string.
Depending on compiler settings, string is either:
shortstring
ansistring
shortstring always has a fixed length, and therefore a shortstring can be at a fixed (and known at compile time) location in memory.
Ansistring can grow to any size. Memory must be allocated on the fly, once the required amount is known. That means behind the scenes ansistring must do memory management too. And store that info.
AnsiString is internally already a pointer, but normally you never will notice.
var
sa: AnsiString;
sb: ShortString[10];
pa := @sa; // something you never want. a pointer to an internal structure of fpc, may change in new fpc versions, not save to access
pa := @sa[1]; // works, but gives a range check, if the string is empty
pa := Pchar(sa); // always good
pb := @sb; // may work, I don't actually know
pb := @sb[1]; //ok, as long as sb was defined with a len of 1 or more
pb := pchar(pb); // good
pa can be nil, if the sa was empty. That may be unexpected, because you can't do "if pa^ = #0"
since the shortstring has a fixed len pb should never be nil