【问题标题】:Dynamic array causing an invalid pointer exception导致无效指针异常的动态数组
【发布时间】:2017-10-24 13:49:02
【问题描述】:

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

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

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

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

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

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

调用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;

看起来指针异常与其中一个动态数组在超出范围时如何被释放有关。

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

我也尝试过使用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.

【问题讨论】:

    标签: arrays delphi dynamic-arrays


    【解决方案1】:

    您的代码没有缺陷,任何错误只能是由于编译器/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 Berlin 有同样的错误。在 Button1Click 结束时第二次调用 System._DynArrayClear 时发生。
    • 更正,10.2 东京。
    • 我也可以在 10 Seattle on Win32 上重现它,但不能在 Win64 上重现。 takeData(localArray + [4, 5, 6]) 似乎也可以正常工作,而 takeData([4, 5, 6] + localArray); 则不行。
    • 使用TData.Create(1, 2, 3) 代替常量表达式[1, 2, 3] 仍然会导致指针异常。我应该提到我使用的是 XE8,但也在 10.2 上重现了这个问题。
    • 由于其他人能够重现该错误,我正在提交错误报告。
    猜你喜欢
    • 2019-03-14
    • 2014-04-02
    • 1970-01-01
    • 1970-01-01
    • 2014-02-05
    • 1970-01-01
    • 1970-01-01
    • 2014-08-02
    • 2015-09-12
    相关资源
    最近更新 更多