Consider I have a procedure with Str
parameter passed by reference, and I want to modify content of the given variable through the procedure, e.g.
procedure Replace(var Str: string);
var
PStr: PChar;
i: Integer;
begin
PStr := @Str[1];
for i := 1 to Length(Str) do begin
PStr^ := 'x';
Inc(PStr);
end;
end;
Is it an acceptable pointer usage? I'm not sure whether it has a memory leak.
What really happen in PStr := @Str[1]
, does compiler make a copy of Str
internally, or what?
Is this kind of code optimization worth?
Is it an acceptable pointer usage?
You need to make sure that you don't call
PStr := @Str[1];
for an empty string, as that would crash. The easiest way to do that is to replace that line with
PStr := PChar(Str);
so that the compiler will make sure that either a pointer to the first char of the string, or a pointer to #0
is returned. As Ken correctly pointed out in a comment there is no call to UniqueString()
in this case, so you would need to do it yourself.
I'm not sure whether it has a memory leak.
No, there is no memory leak. Obtaining a pointer to a string character will call UniqueString()
internally, but that will happen for write access to a string character too, so there's nothing special about the character pointer.
What really happen in PStr := @Str[1], does compiler make a copy of Str internally, or what?
No, it just makes sure that the string is unique (so that write access through the pointer does not change the contents of any other string that shares the same data). Afterwards it returns a pointer to that character in the string, which you can then treat as any other PChar
variable, pass it to API functions, increment it and so on.
Is this kind of code optimization worth?
It is not only worth it, it is necessary to really achieve good performance for large strings. The reason for this is that the compiler is not smart enough to only call UniqueString()
once, but it will insert calls to it for each write access to a character in the string. So if you process a large string character by character you will have a big overhead from all these calls.
Yes, it's safe, as long as you don't go beyond the bounds of the string. The string has metadata attached that tells how long it is, and if you write beyond the length of the string, you won't leak memory, but you could corrupt it.
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