当我尝试将字符串从Lines控件的TMemo传递给PChar数组时,会发生一些奇怪的事情。在例程结束时,将复制数组中的最后一个字符串。我能够用以下简单代码复制它:

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;


如果我逐步运行此过程,则可以看到arr[0] = 'abbb',但是在常规结尾处,arr[0]arr[1]这两个值都等于baaa。我想这与类型转换有关。

谁能看到什么地方不对?

最佳答案

您的代码有两个问题:


您的循环超出了数组的上限。它需要改用for i := 0 to Length(strarr)-1 dofor i := 0 to High(strarr) do
更重要的是,当将AnsiString强制类型转换为PAnsiChar时,如果AnsiString不为空,它将返回指向AnsiString内部数据的指针。您正在将UnicodeString类型转换为AnsiString并抓住一个指针,所以编译器必须对AnsiString数据使用编译器生成的局部变量。换句话说,您的代码实际上正在执行以下操作:

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;



取决于compiler_temp的内存在运行时由RTL内存管理器管理的方式,在这种情况下arr[0]arr[1]最终有可能指向同一物理内存块。

如果要使用PAnsiChar值数组,则需要从Ansi数据数组开始,以使其指向:

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;

09-05 13:21
查看更多