【问题标题】:Assigning to RadioGroup Tag from Form Tag in XE8 causes access violation从 XE8 中的表单标记分配给 RadioGroup 标记会导致访问冲突
【发布时间】:2015-05-07 03:32:25
【问题描述】:

我最近从 XE4 升级到 XE8,在将 itemindex 分配给无线电组时遇到了访问冲突。我很好奇为什么在 XE4 中这行得通,而在 XE8 中却不行。当主程序启动时,所有的表格都已经创建好了。此代码在调试时运行良好,但在独立运行时会引发异常。

with TravelBookingForm do begin
   try
      rg1.itemindex:=tag-1;//not sure which causes the access violation
   except
      on E : Exception do
      begin
         showMessage(E.Message); //access violation message is shown
      end;
      rg1.tag := 0;
   end;
end;

注意:我省略了不相关的代码

【问题讨论】:

  • 去掉with语句,然后调试。确认 TravelBookingForm nil 和 rg1 nil - 虽然如果 TravelBookingForm 是 rg1 的父级,我猜 TravelBookingForm 尚未创建
  • 如果您不确定 AV 是来自 ItemIndex 分配还是来自 Tag 阅读,请将它们拆分为单独的语句。将Tag 读入一个局部变量,然后将其分配给ItemIndex
  • 在项目源码中我们有:Application.CreateForm(TTravelBookingForm, TravelBookingForm);所以我认为它正在被创建
  • 如果你在 with 语句上放置一个断点并检查,你会知道(或不知道)它正在被创建。它会消除猜测的工作
  • 所以经过更多测试后,我可以确认 rg1 不是 nil 并且它是导致访问冲突的项目

标签: forms delphi access-violation delphi-xe8


【解决方案1】:

所以经过更多测试后,我可以确认 rg1 不是 nil 并且它是导致访问冲突的项目。

如果rg1 不是nil 并且导致访问冲突,那么最合理的解释是rg1 指向已释放的内存。这与错误有时发生(在调试器外部)而不是其他情况(在调试器下)的观察结果相符。

所以,您的程序会在某个时候销毁表单,然后再引用该表单。

很明显,这是您的程序中的一个错误,您需要确保在表单被销毁后​​您永远不会引用它们。不幸的是,IDE 鼓励您在启动时创建所有表单,并在全局变量中保存引用。这使得拥有过时的引用变得太容易了。

如果您使用 FastMM 的完整调试版本,那么该工具将能够在您尝试访问已释放的内存时向您发出警告。

【讨论】:

  • 我已尝试创建表单的本地版本:TravelBookingForm : TTravelBookingForm; TravelBookingForm := TTravelBookingForm.Create(main);并使用它,但我们仍然遇到相同的访问冲突?
  • 也试过 Application.createForm(TTravelBookingForm, TravelBookingForm);结果相同
  • 无论如何我都找不到我们释放它,使用 TravelBookingForm.free TravelBookingForm.destroy freeandnil(TravelBookingForm)
  • 使用调试器。检测破坏。可能是OnDestroy,或者被覆盖的Destroy
  • 只有在应用程序按预期关闭时才会调用表单 onDestroy 方法。我找不到它正在被摧毁的其他地方。此代码在 XE4 中运行良好
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2011-11-04
  • 1970-01-01
  • 2020-10-12
  • 1970-01-01
  • 1970-01-01
  • 2010-11-05
相关资源
最近更新 更多