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?

+3


source to share


1 answer


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 instead for i := 0 to High(strarr) do

    .

  • More importantly, when you type AnsiString

    in PAnsiChar

    , it returns a pointer to the internal data AnsiString

    if AnsiString

    not empty. You are producing a type UnicodeString

    in AnsiString

    and grabbing a pointer to it, so the compiler must use a compiler-generated local variable for the data AnsiString

    . 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;

      

+5


source







All Articles