Warning: file_get_contents(/data/phpspider/zhask/data//catemap/9/delphi/9.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Delphi 使用记录时,访问TListItem.Data会导致错误_Delphi_Record_Tlistview - Fatal编程技术网

Delphi 使用记录时,访问TListItem.Data会导致错误

Delphi 使用记录时,访问TListItem.Data会导致错误,delphi,record,tlistview,Delphi,Record,Tlistview,我有一个程序,它使用TListView来可视化和存储一些数据TListitem的数据属性由指向记录的指针填充,如下所示: type TWatch = record name : string; path : string; //... end; procedure TfrmProcessWatcherMain.AddWatchToListView(AWatch: TWatch); var ANewWatch : TListItem; begin ANewWa

我有一个程序,它使用
TListView
来可视化和存储一些数据
TListitem
的数据属性由指向记录的指针填充,如下所示:

type
  TWatch = record
    name : string;
    path : string;
    //...
end;

procedure TfrmProcessWatcherMain.AddWatchToListView(AWatch: TWatch);
var
  ANewWatch : TListItem;
begin
  ANewWatch := lvWatches.Items.Add; //lvWatches is TListview
  //...
  ANewWatch.Data:= @AWatch;
end;
当我试图以某种方式检索这些数据时,我遇到了访问冲突错误,这对我来说完全是一个惊喜,因为一切似乎都是合法的,以下是检索代码:

if(lvWatches.Selected <> nil) then begin
  tempWatch := TWatch(lvWatches.Selected.Data^); // AV here
  ShowMessage(tempWatch.name);

因此可以使用其他方法访问它

问题在于
@AWatch
是局部变量的地址。只要
AddWatchToListView
返回
AWatch
超出范围,并且该地址不再有效

您需要使用
New
在堆上分配记录,而不是获取局部变量的地址

procedure TfrmProcessWatcherMain.AddWatchToListView(AWatch: TWatch);
var
  ANewWatch : TListItem;
  P : ^TWatch;
begin
  ANewWatch := lvWatches.Items.Add;
  New(P);
  P^ := AWatch;
  ANewWatch.Data:= P;
end;
每当列表项被销毁时,您需要使用
Dispose
释放内存。使用列表视图的
ondelection
事件执行此操作


或者,您可以将该项的索引存储在
监视列表中。或者
监视列表中记录的地址,如下所示:
@WatchList.List[Index]
。这两个选项都依赖于
观察列表
在引用项目后不会被修改,这对您来说可能太过约束

问题在于
@AWatch
是局部变量的地址。只要
AddWatchToListView
返回
AWatch
超出范围,并且该地址不再有效

您需要使用
New
在堆上分配记录,而不是获取局部变量的地址

procedure TfrmProcessWatcherMain.AddWatchToListView(AWatch: TWatch);
var
  ANewWatch : TListItem;
  P : ^TWatch;
begin
  ANewWatch := lvWatches.Items.Add;
  New(P);
  P^ := AWatch;
  ANewWatch.Data:= P;
end;
每当列表项被销毁时,您需要使用
Dispose
释放内存。使用列表视图的
ondelection
事件执行此操作


或者,您可以将该项的索引存储在
监视列表中。或者
监视列表中记录的地址,如下所示:
@WatchList.List[Index]
。这两个选项都依赖于
观察列表
在引用项目后不会被修改,这对您来说可能太过约束

问题在于
@AWatch
是局部变量的地址。只要
AddWatchToListView
返回
AWatch
超出范围,并且该地址不再有效

您需要使用
New
在堆上分配记录,而不是获取局部变量的地址

procedure TfrmProcessWatcherMain.AddWatchToListView(AWatch: TWatch);
var
  ANewWatch : TListItem;
  P : ^TWatch;
begin
  ANewWatch := lvWatches.Items.Add;
  New(P);
  P^ := AWatch;
  ANewWatch.Data:= P;
end;
每当列表项被销毁时,您需要使用
Dispose
释放内存。使用列表视图的
ondelection
事件执行此操作


或者,您可以将该项的索引存储在
监视列表中。或者
监视列表中记录的地址,如下所示:
@WatchList.List[Index]
。这两个选项都依赖于
观察列表
在引用项目后不会被修改,这对您来说可能太过约束

问题在于
@AWatch
是局部变量的地址。只要
AddWatchToListView
返回
AWatch
超出范围,并且该地址不再有效

您需要使用
New
在堆上分配记录,而不是获取局部变量的地址

procedure TfrmProcessWatcherMain.AddWatchToListView(AWatch: TWatch);
var
  ANewWatch : TListItem;
  P : ^TWatch;
begin
  ANewWatch := lvWatches.Items.Add;
  New(P);
  P^ := AWatch;
  ANewWatch.Data:= P;
end;
每当列表项被销毁时,您需要使用
Dispose
释放内存。使用列表视图的
ondelection
事件执行此操作



或者,您可以将该项的索引存储在
监视列表中。或者
监视列表中记录的地址,如下所示:
@WatchList.List[Index]
。这两个选项都依赖于
观察列表
在引用项目后不会被修改,这对您来说可能太过约束

本地变量
ANewWatch
和相关数据在外部不可用
AddWatchToListView
。使用动态分配的指针。局部变量
ANewWatch
和相关数据在
AddWatchToListView
外部不可用。使用动态分配的指针。局部变量
ANewWatch
和相关数据在
AddWatchToListView
外部不可用。使用动态分配的指针。局部变量
ANewWatch
和相关数据在
AddWatchToListView
外部不可用。使用动态分配的指针。为什么不使用指向
观察列表
中已分配记录的项目的指针呢?@LURD您可以这样做,前提是在引用后观察列表未被修改。谢谢,我认为函数参数是通过引用传递的,而不是实例化新的局部变量,因此,
AWatch
不是本地变量,而是对列表项的引用。至于
@WatchList.List[Index]
这会更简单,但您不能使用指向属性的指针,所以我使用WatchList Index作为参考
AddWatchToListView(AWatch:TWatch;WatchIndex:integer)
AWatch
是一个按值参数,使其成为局部变量。它不是通过引用传递的。这是因为记录是值类型而不是引用类型。我怀疑这是你根本的错误想法
TList.List
是一个动态数组
@WatchList.List[Index]
是引用列表内部成员的方法。但是,如果在引用后修改列表,则没有用。所以可能不推荐。是的,没错。我在大多数情况下都使用类,所以我已经忘记了这一点。我刚刚意识到我的
TList
中没有
列表
字段,不知道为什么,可能不是那个版本,或者列表中没有什么东西?顺便说一句,我用的是XE2。之前我以为你指的是物品。至于修改,当我更改监视列表时,listview也会更改,因此它依赖于实际信息,为什么不使用指向已更改的
监视列表中的项的指针呢