Delphi 2007 MDI表单销毁序列问题

时间:2015-04-20 20:49:04

标签: delphi memory-leaks

我有一个奇怪的问题,我似乎无法弄明白。我有一个MDI子窗体,上面有一个TListView组件。在此列表视图中,我添加了一些列表项,其数据属性指向相关对象。在OnFormDestroy事件中,我执行类似于以下操作来清理这些对象:

Procedure TMDIChildForm1.FormDestroy(Sender: TObject);
Begin
  For I := 0 To lvLabour.Items.Count - 1 Do
    TLabourItem(lvLabour.Items[I].Data).Free;
  lvLabour.Items.Clear;
End;

现在,如果我关闭表单本身但保持应用程序打开,这样可以正常工作。它将遍历每个项目释放相关对象。但是,如果我只是在没有先关闭MDI表单的情况下完全关闭应用程序,当它到达上面的代码时,项目计数为0.这意味着在调用FormDestroy方法之前,项目已从列表中清除。

因为只有当应用程序正在关闭时才会发生这种情况,因此没有内存泄漏。我只是将应用程序设置为在调试时显示内存泄漏,当我收到内存泄漏消息时它会让我烦恼并且无法弄清楚原因。

1 个答案:

答案 0 :(得分:2)

这种情况正在发生,因为终止过程无论出于何种原因,都会在代码运行之前清除列表视图。但是有更好的方法可以解决这个问题。好吧,还有一些更诚实的方法。

从最接近你的位置开始,你应该使用列表视图的OnDeletion事件来执行项目整理。删除列表项时会触发此事件。您的事件处理程序将具有此原型:

procedure ListView1Deletion(Sender: TObject; Item: TListItem);

在此事件处理程序中,对Free中保留的对象调用Item.Data。通过这种方式,无论列表及其项目如何被销毁,您都确信相关数据已被销毁。

我建议的另一种方法涉及更多工作。使用虚拟列表视图,而不是包含对数据的引用的列表项。在这种操作模式中,只要列表视图控件需要绘制项目或查询其属性和状态,它就会调用控件的事件来获取按需信息。这可以避免您需要将数据对象的生命周期与显示它的GUI的生命周期相结合。