0

我有一个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传递给第一个函数的也存储在

WatchList : TList<TWatch>;

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

4

1 回答 1

3

问题是这@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每当列表项被销毁时,您都需要释放内存。使用列表视图的OnDeletion事件来做到这一点。

或者,您可以将项目的索引存储在WatchList. 或者记录的地址WatchList,你会得到这样的:@WatchList.List[Index]。这两个选项都依赖于WatchList在引用项目后不被修改,这对您来说可能过于约束。

于 2015-03-29T08:25:50.493 回答