动态数组导致无效指针异常

Joh*_*eek 11 arrays delphi dynamic-arrays

我有一个将动态数组TData = TArray<Byte>作为参数的过程.

procedure DoStuff(const Input: TData);
begin
  // do nothing
end;
Run Code Online (Sandbox Code Playgroud)

还有一个返回动态数组的函数.

function SomeData: TData;
begin
  Result := [1, 2];
end;
Run Code Online (Sandbox Code Playgroud)

当我使用下面示例中的过程时,DoStuff获取以下数据(1,2,3,1,3),但在DoStuff完成后我得到一个EInvalidPointer异常.

procedure TForm1.Button1Click(Sender: TObject);
begin    
  DoStuff([1, 2, 3] + SomeData);
end;
Run Code Online (Sandbox Code Playgroud)

调用DoStuff([1, 2] + SomeData);不会导致错误,当数组大于4项时,它似乎变得敏感.如果我使用临时变量来保存数组,DoStuff仍会得到(1,2,3,1,2),但没有错误.

procedure TForm1.Button2Click(Sender: TObject);
var
  Temp: TData;
begin
  Temp := [1, 2, 3] + SomeData;

  DoStuff(Temp);
end;
Run Code Online (Sandbox Code Playgroud)

看起来像指针异常与其中一个动态数组超出范围时的释放有关.

我不应该以这种方式使用动态数组吗?工作时,这非常干净地解决了我当前的问题.

我也试过使用array of Byte;而不是TArray<Byte>;但有相同的结果.

完整的测试单位:

unit Main;

interface

uses
  Winapi.Windows, Winapi.Messages, System.SysUtils, System.Variants,
  System.Classes, Vcl.Graphics,
  Vcl.Controls, Vcl.Forms, Vcl.Dialogs, Vcl.StdCtrls;

type
  TData = TArray<Byte>;

  TForm1 = class(TForm)
    Button1: TButton;
    Button2: TButton;
    procedure Button1Click(Sender: TObject);
    procedure Button2Click(Sender: TObject);
  private
    { Private declarations }
  public
    { Public declarations }
  end;

procedure DoStuff(const Input: TData);
function SomeData: TData;

var
  Form1: TForm1;

implementation

{$R *.dfm}

procedure TForm1.Button1Click(Sender: TObject);
begin
  DoStuff([1, 2, 3] + SomeData);
end;

procedure TForm1.Button2Click(Sender: TObject);
var
  Temp: TData;
begin
  Temp := [1, 2, 3] + SomeData;

  DoStuff(Temp);
end;

procedure DoStuff(const Input: TData);
begin
  // do nothing
end;

function SomeData: TData;
begin
  Result := [1, 2];
end;

end.
Run Code Online (Sandbox Code Playgroud)

Dav*_*nan 8

您的代码没有缺陷,任何错误只能归因于编译器/ RTL错误.

+首次发布时,对动态数组文字和动态数组运算符的支持有些不完整.XE7中添加了这些功能,我相信大多数错误都是由XE8解决的.

我的猜测是你正在使用XE7,或者可能是一个层版本,它仍然包含比XE7中许多明显错误更隐蔽的错误.

您的选择似乎是:

  1. 更新到以后的Delphi版本.
  2. 通过避免使用+带有动态数组和/或动态数组文字的运算符来解决代码问题.

我仍然使用XE7并使用我自己的通用连接函数解决问题.可以在此处找到如何执行此操作的示例:https://stackoverflow.com/a/15924484/505088

这样的解决方法可以帮助您避免+操作员的问题,但如果问题在于处理数组文字,则不会.如果你的问题是数组文字,那么你可能最终需要用来TData.Create(1, 2, 3)代替[1, 2, 3].

如果缺陷出现在更高版本中,请向Embarcadero的质量门户提交错误报告.

  • Delphi 10.2柏林也有同样的错误.当Button1Click结束时第二次调用System._DynArrayClear时发生. (2认同)