首页 > 解决方案 > delphi 在使用函数和数组时出错

问题描述

图片

当我通过函数填充数组时会发生此错误。该函数使用存储在文本文件中的所有详细信息填充数组。该代码可以填充数组,但是当我尝试在函数中使用它时它不起作用。

type
  DynamicArray = array of string; 

Function fillarr(ArrParm: DynamicArray; FileName: String): DynamicArray;
Var
  tf: TextFile;
  sWord: String;
  i: Integer;
begin
  i := 0;
  SetLength(ArrParm, 1);
  AssignFile(tf, FileName);
  Reset(tf);
  while not eof(tf) do
  begin
    Readln(tf, sWord);
    ArrParm[i] := sWord;
    Inc(i);
    SetLength(ArrParm, i + 1);
  end;
  SetLength(ArrParm, i - 1);
  Result := ArrParm;
end;

procedure TForm4.FormShow(Sender: TObject);
Var
  arrPictures: DynamicArray;
begin
  FillArr(arrPictures, 'NameOfTheTextFile.txt');
  ShowMessage(arrPictures[1]); // Error occurs here

标签: arraysimagefunctiondelphi

解决方案


您必须了解动态数组是引用类型,但引用是按值传递的。

TForm4.FormShow中,您有一个动态数组变量arrPictures。即使这是一个局部变量,它也会被初始化,因为它是一个动态数组,它是一种托管类型。具体来说,它的开头是nil一个零长度的动态数组)。因此,第二个元素arrPictures[1]在此方法开始时不存在。

您尝试通过调用来填充数组FillArr。但是,当您传递arrPictures给此方法时,引用是按值传递的,因此FillArr获得了指向动态数组堆对象的指针的副本

现在,该SetLength过程重新分配了动态数组堆对象,因此指向它的指针必须改变。换句话说,ArrParm变量的值发生变化,指向一个新的动态数组堆对象。最初的,它TForm4.FormShow是有意识的,保持不变。(但在这种情况下它根本不存在,因为数组nil的长度为零。)

因此,当fillarr返回时,arrPictures仍然是nil,并且arrPictures[1]仍然不存在。所以你得到一个 AV 试图阅读它。

解决办法是把数组参数做成var参数,这样动态数组变量是通过引用传递的。这样,当FillArr更改指针的值时,此更改将对 in 中的变量可见TForm4.FormShow

function fillarr(var ArrParm: DynamicArray; FileName: string): DynamicArray;

(fillarr是一个函数,它实际上返回了新数组。但是当你在 中调用这个函数时TForm4.FormShow,你会丢弃结果值,所以你不会因为它是一个函数而获得任何收益。但这意味着不同的解决方案是不丢弃结果值。但是您可以完全删除参数。您不需要或不希望例程有两种方法返回相同的值。要么让它成为一个带varorout参数的过程,要么让它成为一个不带参数的函数.)


除了这个问题,代码还有其他问题。例如,试着想想你是如何阅读文件的。你能用更少的SetLength电话做到这一点吗?

(但在实际应用程序中,根本不应该使用传统的 Pascal I/O,并且应该“从不”一次增加一个动态数组或字符串的大小。)


推荐阅读