【问题标题】:Why "menus" unit is finalized too early?为什么“菜单”单元过早完成?
【发布时间】:2010-03-26 17:16:55
【问题描述】:

我在 FastMM 和 FullDebugMode 开启的情况下测试了我的应用程序,因为我遇到了一些关机问题。

在解决了我自己的一堆问题后,FastMM 开始抱怨在 TPopupList 中的已释放对象上调用虚拟方法。我试图在使用中尽早移动菜单单元,以便最后完成,但它没有帮助。这是真正的问题,vcl 中的错误还是 FastMM 的误报?

这是来自 FastMM 的完整报告:

FastMM has detected an attempt to call a virtual method on a freed object. An access violation will now be raised in order to abort the current operation.

Freed object class: TPopupList

Virtual method: Offset +16

Virtual method address: 4714E4

The allocation number was: 220

The object was allocated by thread 0x1CC0, and the stack trace (return addresses) at the time was:
403216 [sys\system.pas][System][System.@GetMem][2654]
404A4F [sys\system.pas][System][System.TObject.NewInstance][8807]
404E16 [sys\system.pas][System][System.@ClassCreate][9472]
404A84 [sys\system.pas][System][System.TObject.Create][8822]
7F2602 [Menus.pas][Menus][Menus.Menus][4223]
40570F [sys\system.pas][System][System.InitUnits][11397]
405777 [sys\system.pas][System][System.@StartExe][11462]
40844F [SysInit.pas][SysInit][SysInit.@InitExe][663]
7F6368 [PCCSServer.dpr][PCCSServer][PCCSServer.PCCSServer][148]
7C90DCBA [ZwSetInformationThread]
7C817077 [Unknown function at RegisterWaitForInputIdle]

The object was subsequently freed by thread 0x1CC0, and the stack trace (return addresses) at the time was:
403232 [sys\system.pas][System][System.@FreeMem][2699]
404A6D [sys\system.pas][System][System.TObject.FreeInstance][8813]
404E61 [sys\system.pas][System][System.@ClassDestroy][9513]
428D15 [common\Classes.pas][Classes][Classes.TList.Destroy][2914]
404AB3 [sys\system.pas][System][System.TObject.Free][8832]
472091 [Menus.pas][Menus][Menus.Finalization][4228]
4056A7 [sys\system.pas][System][System.FinalizeUnits][11256]
4056BF [sys\system.pas][System][System.FinalizeUnits][11261]
7C9032A8 [RtlConvertUlongToLargeInteger]
7C90327A [RtlConvertUlongToLargeInteger]
7C92AA0F [Unknown function at towlower]

The current thread ID is 0x1CC0, and the stack trace (return addresses) leading to this error is:
4714B8 [Menus.pas][Menus][Menus.TPopupList.MainWndProc][3779]
435BB2 [common\Classes.pas][Classes][Classes.StdWndProc][11583]
7E418734 [Unknown function at GetDC]
7E418816 [Unknown function at GetDC]
7E428EA0 [Unknown function at DefWindowProcW]
7E428EEC [Unknown function at DefWindowProcW]
7C90E473 [KiUserCallbackDispatcher]
7E42B1A8 [DestroyWindow]
47CE31 [Controls.pas][Controls][Controls.TWinControl.DestroyWindowHandle][6857]
493BE4 [Forms.pas][Forms][Forms.TCustomForm.DestroyWindowHandle][4564]
4906D9 [Forms.pas][Forms][Forms.TCustomForm.Destroy][2929]

Current memory dump of 256 bytes starting at pointer address 7FF9CFF0:
2C FE 82 00 80 80 80 80 80 80 80 80 80 80 80 80 80 80 80 80 C4 A3 2D 0C 00 00 00 00 B1 D0 F9 7F
00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 C0 00 00 00 16 32 40 00 9D 5B 40 00 C8 5B 40 00
CE 82 40 00 3C 40 91 7C B0 B1 94 7C 0A 77 92 7C 84 77 92 7C 7C F0 96 7C 94 B3 94 7C 84 77 92 7C
C0 1C 00 00 32 32 40 00 12 5B 40 00 EF 69 40 00 BA 20 47 00 A7 56 40 00 BF 56 40 00 A8 32 90 7C
7A 32 90 7C 0F AA 92 7C 0A 77 92 7C 84 77 92 7C C0 1C 00 00 0E 00 00 00 00 00 00 00 C7 35 65 59
2C FE 82 00 80 80 80 80 80 80 80 80 80 80 38 CA 9A A6 80 80 80 80 80 80 00 00 00 00 51 D1 F9 7F
00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 C1 00 00 00 16 32 40 00 9D 5B 40 00 C8 5B 40 00
CE 82 40 00 3C 40 91 7C B0 B1 94 7C 0A 77 92 7C 84 77 92 7C 7C F0 96 7C 94 B3 94 7C 84 77 92 7C
,  þ  ‚  .  €  €  €  €  €  €  €  €  €  €  €  €  €  €  €  €  Ä  £  -  .  .  .  .  .  ±  Ð  ù  
.  .  .  .  .  .  .  .  .  .  .  .  .  .  .  .  À  .  .  .  .  2  @  .    [  @  .  È  [  @  .
Î  ‚  @  .  <  @  ‘  |  °  ±  ”  |  .  w  ’  |  „  w  ’  |  |  ð  –  |  ”  ³  ”  |  „  w  ’  |
À  .  .  .  2  2  @  .  .  [  @  .  ï  i  @  .  º     G  .  §  V  @  .  ¿  V  @  .  ¨  2    |
z  2    |  .  ª  ’  |  .  w  ’  |  „  w  ’  |  À  .  .  .  .  .  .  .  .  .  .  .  Ç  5  e  Y
,  þ  ‚  .  €  €  €  €  €  €  €  €  €  €  8  Ê  š  ¦  €  €  €  €  €  €  .  .  .  .  Q  Ñ  ù  
.  .  .  .  .  .  .  .  .  .  .  .  .  .  .  .  Á  .  .  .  .  2  @  .    [  @  .  È  [  @  .
Î  ‚  @  .  <  @  ‘  |  °  ±  ”  |  .  w  ’  |  „  w  ’  |  |  ð  –  |  ”  ³  ”  |  „  w  ’  |

我使用的是 Delphi 2007 和 FastMM 4.97。

Edit1:我认为这里的主要问题是为什么 Classes.StdWndProc 调用 Menus.TPopupList?在调试器中挖掘调用堆栈显示 System.FinalizeUnit 被调用了 3 次,然后它转到 SysUtils.ShowException,它尝试显示 MessageBox,在一堆 user32.dll 调用之后,我们最终到达 classes.StdWndProc。

Edit2:我遇到了接口问题,解决了这个问题。带有接口的对象被释放,但引用被释放。当接口被释放时,发生了一个我最初以某种方式忽略的异常。释放接口可能会损坏一些导致所有其他问题的东西。

【问题讨论】:

    标签: delphi debugging delphi-2007 fastmm


    【解决方案1】:

    当一个单元在它间接依赖的另一个单元之后完成时,就会发生这种情况。

    以下列单位为例:

    unit Unit1;
    interface
    uses
      Contnrs;
    
    var
      ItemHolder : TObjectList;
    
    implementation
    
    initialization
      ItemHolder := TObjectList.Create(True);
    finalization
      ItemHolder.Free;
    end.
    

    该单元仅直接依赖于 Contnrs。出于这个原因,delphi 将确保这个单元在 Contnrs 之前完成。如果 ObjectList 包含 TForms,Delphi 不会确保 Unit1 在单元 Forms 之前完成。如果关闭应用程序时仍有一些表单,TObjectList(因为它拥有该对象)将释放它包含的项目(调用 TForm.Free)。但是由于 Unit1 不依赖于 TForm,因此单元 Forms 可能已经完成,并且 TForm.Destroy 不再在内存中。

    这就是为什么您需要非常小心在完成部分中所做的事情。

    我不确定这是你问题的根源,但我会先这样看。

    【讨论】:

      【解决方案2】:

      我以前在 Delphi 2007 中看到过这样的问题。有时编译器会感到困惑并生成不正确的初始化或完成顺序。遗憾的是,我始终无法创建可重现的测试用例发送给 CodeGear/Embarcadero 人员。

      无论何时发生,全面重建都会有所帮助。

      【讨论】:

        【解决方案3】:

        确保 FastMM4 是项目文件的 uses 子句(项目|查看源代码)中的第一行。如果不存在,则添加它。

        【讨论】:

          【解决方案4】:

          在完成 Menus.pas 后,您的一个表单似乎正在销毁。如果您的表单上有一个菜单,那么它可能必须在 interface 部分的 uses 列表中包含 Menus,这应该是不可能的。

          我唯一一次看到这样的问题弹出(不是双关语)是在使用包时。您是否正在使用带有插件的 DPK,该插件会在您的程序中添加弹出菜单或菜单项?如果你不小心,包终结可能会对你的程序造成一些奇怪的事情。

          无论哪种方式,解决方案可能是在 menus.pas 完成之前自己处理菜单。当程序需要关闭时,请在弹出菜单上调用 Free,看看是否可以解决问题。

          【讨论】:

          • 是的,这就是问题的重点,为什么 menus.pas 在所有表格都完成之前过早完成。我不确定这些包裹,我认为应该没有那种包裹,但我必须检查一下。
          【解决方案5】:

          更新:这只是部分解决方法

          解决方法: 在你的应用程序的主要形式写

          finalization
            FreeAndNil(PopupList);
          end.
          

          这个空闲的PopupList并设置为nil,这样menus.pas中的PopupList.Free就可以了。

          【讨论】:

            猜你喜欢
            • 2018-06-13
            • 1970-01-01
            • 2011-02-24
            • 2013-07-20
            • 2022-11-14
            • 2011-01-12
            • 1970-01-01
            • 1970-01-01
            • 1970-01-01
            相关资源
            最近更新 更多