动态数组导致无效指针异常
Dynamic array causing an invalid pointer exception
我有一个将动态数组 TData = TArray<Byte>
作为参数的过程。
procedure DoStuff(const Input: TData);
begin
// do nothing
end;
还有一个函数,returns一个动态数组。
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.
您的代码没有缺陷,任何错误都只能是由于编译器/RTL 错误。
动态数组文字和动态数组 +
运算符的支持在首次发布时有些不完整。这些功能是在 XE7 中添加的,我相信大部分错误都已在 XE8 中解决。
我的猜测是您使用的是 XE7,或者可能是一个图层版本,它仍然包含一个比 XE7 中许多明显的错误更隐蔽的错误。
您的选择似乎是:
- 更新到更高的 Delphi 版本。
- 通过避免对动态数组和/或动态数组文字使用
+
运算符来解决代码问题。
我仍然使用 XE7 并使用我自己的通用串联函数解决问题。可以在此处找到如何执行此操作的示例:
此类解决方法可帮助您避免 +
运算符出现问题,但如果问题与处理数组文字有关,则不会。如果您的问题出在数组文字上,那么您最终可能需要使用 TData.Create(1, 2, 3)
代替 [1, 2, 3]
.
如果此缺陷出现在更高版本中,请向 Embarcadero 的质量门户网站提交错误报告。
我有一个将动态数组 TData = TArray<Byte>
作为参数的过程。
procedure DoStuff(const Input: TData);
begin
// do nothing
end;
还有一个函数,returns一个动态数组。
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.
您的代码没有缺陷,任何错误都只能是由于编译器/RTL 错误。
动态数组文字和动态数组 +
运算符的支持在首次发布时有些不完整。这些功能是在 XE7 中添加的,我相信大部分错误都已在 XE8 中解决。
我的猜测是您使用的是 XE7,或者可能是一个图层版本,它仍然包含一个比 XE7 中许多明显的错误更隐蔽的错误。
您的选择似乎是:
- 更新到更高的 Delphi 版本。
- 通过避免对动态数组和/或动态数组文字使用
+
运算符来解决代码问题。
我仍然使用 XE7 并使用我自己的通用串联函数解决问题。可以在此处找到如何执行此操作的示例:
此类解决方法可帮助您避免 +
运算符出现问题,但如果问题与处理数组文字有关,则不会。如果您的问题出在数组文字上,那么您最终可能需要使用 TData.Create(1, 2, 3)
代替 [1, 2, 3]
.
如果此缺陷出现在更高版本中,请向 Embarcadero 的质量门户网站提交错误报告。