【问题标题】:Delphi - invalid pointer operation when closing the application from the taskbar menuDelphi - 从任务栏菜单关闭应用程序时指针操作无效
【发布时间】:2013-02-17 10:57:55
【问题描述】:

我有一个应用程序将所有动态创建的数据模块加载到 TList 中。应用程序在 windows XP 操作系统下运行。从应用程序关闭按钮关闭应用程序时,代码会正确执行。但是当从任务栏菜单关闭应用程序时,会引发无效指针操作。相同的代码在以不同方式关闭应用程序时表现不同。

负责销毁数据模块的代码

  for iPos := 0 to FDatamodules.Count - 1 do //FDataModules is of type TList
    if FDatamodules.Items[iPos] <> nil then 
      TDatamodule(FDatamodules.Items[iPos]).Free;

和堆栈

:7c812a6b kernel32.RaiseException + 0x52
System.TObject.FreeInstance
System.ErrorAt(2,$4A7FEFC)
System.Error(reInvalidPtr)
System.TObject.FreeInstance
System._ClassDestroy(???)
Classes.TDataModule.Destroy
System.TObject.Free
RBAFORM.TRBABaseForm.Destroy

LE:似乎从任务栏菜单关闭应用程序正在向应用程序发送 HALT(0) 并且数据模块被释放。在下图中:左边是正常关闭操作的堆栈,右边是从任务栏菜单关闭应用程序的堆栈。

【问题讨论】:

  • 如何创建数据模块? Create(Nil) 应该是这里的正确方式。
  • @LURD - 我不明白为什么从应用程序关闭按钮关闭应用程序时这段代码可以工作,但是从任务栏菜单关闭它时会崩溃。执行相同的代码,但从任务栏菜单关闭它时崩溃。
  • 这可能是 David 解释的,具体取决于释放数据模块的顺序。如果你先手动销毁数据模块是可以的,但是其他的方式就不行了。可能存在先出现的竞争条件。
  • 双倍释放并不总是运行时错误。有时你运气不好,它运行时没有错误。
  • Jens' 将是您提供的信息级别最具体的答案。

标签: delphi delphi-xe


【解决方案1】:

这似乎是一个双重释放问题(就像 LU 对您的问题发表的评论一样),这意味着您不止一次释放数据模块的实例。

当您使用Create(nil) 创建实例时,它不属于任何人,您可以安全地调用Free。 (另见What is the meaning of nil owner in component constructor)

如果您使用Create(Form1)(非零参数)创建它,那么调用Free 不再是您的责任。在本例中Form1 被释放时会自动释放。

要确定发生了什么,您应该在 FullDebugMode 或类似的内存调试器中使用 FastMM。内存调试器应该能够发现问题并为您提供更多有用的信息。

【讨论】:

  • 如果您创建了一个拥有的组件,那么手动释放它仍然可以。它将通知所有者将其从其拥有的组件列表中删除。但是如果所有者先宕机,那么无效的指针 op 是可能的。 +1
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 2011-05-25
  • 2012-04-24
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多