CR in his recent post about the quality of Delphi help discussed the StrUpper/StrLower code example. I was interested why the original D7 example causes an access violation while the similar D2009 example runs without AV. So I have written the following tests (in Delphi 2009):
{$WRITEABLECONST OFF} var S1: PChar = 'A fUnNy StRiNg 1'; S2: string = 'A fUnNy StRiNg 2'; S3: array[0..20] of Char = 'A fUnNy StRiNg 3'; const S4: array[0..20] of Char = 'A fUnNy StRiNg 4'; procedure TForm1.Button1Click(Sender: TObject); var S: string; begin S:= S1; Canvas.TextOut(5, 10, string(StrLower(PChar(S)))); end; procedure TForm1.Button2Click(Sender: TObject); var S: string; begin S:= S2; UniqueString(S); Canvas.TextOut(5, 10, string(StrLower(PChar(S)))); end; procedure TForm1.Button3Click(Sender: TObject); begin Canvas.TextOut(5, 10, string(StrLower(S3))); end; procedure TForm1.Button4Click(Sender: TObject); begin Canvas.TextOut(5, 10, string(StrLower(S4))); end;
Usually inplace functions like StrUpper/StrLower results in AV because the compiler places string constants in read-only memory. A string should be copied to the heap beforehand. In Button1Click procedure the string copy is made implicitly by assigning PChar to string; in Button2Click procedure one should call UniqueString to create a copy.
But that is not the case with the Button3Click example (which is actually the example from Delphi 2009 help). No copy is created here, still the example runs fine and demonstrates that the static arrays of characters are not placed in read-only memory. More than that, the Button4Click is also OK (I have explicitly included {$WRITEABLECONST OFF} directive, though it is OFF by default, to make the case more clear).