How can I pass a string to PAnsiChar array?
Something strange happens when I try to pass strings from a Lines
control TMemo
to an array PChar
. At the end of the procedure, the last line in the array is duplicated. I was able to reproduce this in this simple code:
procedure Test;
var
i: smallint;
arr: array of PAnsiChar;
strarr: array[0..1] of string;
begin
SetLength(arr, 2);
strarr[0] := 'abbb';
strarr[1] := 'baaa';
for i := 0 to Length(strarr) do
arr[i] := PAnsiChar(AnsiString(strarr[i]));
end;
If I run this procedure step by step, I can see arr[0] = 'abbb'
, however at the end of the line both values arr[0]
and arr[1]
are equal baaa
. I'm guessing it has something to do with the type.
Anyone can figure out what is wrong?
source to share
There are two problems in the code:
-
Your loop exceeds the upper bound of the array. Use
for i := 0 to Length(strarr)-1 do
or insteadfor i := 0 to High(strarr) do
. -
More importantly, when you type
AnsiString
inPAnsiChar
, it returns a pointer to the internal dataAnsiString
ifAnsiString
not empty. You are producing a typeUnicodeString
inAnsiString
and grabbing a pointer to it, so the compiler must use a compiler-generated local variable for the dataAnsiString
. In other words, your code effectively does the same as the following:procedure Test; var i: smallint; arr: array of PAnsiChar; strarr: array[0..1] of string; compiler_temp: AnsiString; begin SetLength(arr, 2); strarr[0] := 'abbb'; strarr[1] := 'baaa'; for i := 0 to Length(strarr) do begin compiler_temp := AnsiString(strarr[i]); arr[i] := PAnsiChar(compiler_temp); end; end;
Depending on how the memory compiler_temp
is controlled by the controller RTL memory during execution, it is possible that arr[0]
, and arr[1]
in this situation can point to the same physical memory unit.
If you want an array of values PAnsiChar
, you need to start with an array of data Ansi
so that they point to:
procedure Test;
var
i: Integer;
arr: array of PAnsiChar;
strarr: array[0..1] of AnsiString;
begin
SetLength(arr, 2);
strarr[0] := 'abbb';
strarr[1] := 'baaa';
for i := 0 to Length(strarr)-1 do
arr[i] := PAnsiChar(strarr[i]);
end;
source to share