Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Is it safe to modify the content of a string variable through a pointer?

Tags:

delphi

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?

like image 844
Astaroth Avatar asked Jan 22 '23 01:01

Astaroth


2 Answers

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.

like image 84
mghie Avatar answered Feb 02 '23 00:02

mghie


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.

like image 24
Mason Wheeler Avatar answered Feb 01 '23 23:02

Mason Wheeler