2010-03-26 60 views
1

我打开FastMM和FullDebugMode测试了我的应用程序,因为我有一些关机问题。为什么“菜单”单元过早完成?

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

下面是从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][[email protected]][2654] 
404A4F [sys\system.pas][System][System.TObject.NewInstance][8807] 
404E16 [sys\system.pas][System][[email protected]][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][[email protected]][11462] 
40844F [SysInit.pas][SysInit][[email protected]][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][[email protected]][2699] 
404A6D [sys\system.pas][System][System.TObject.FreeInstance][8813] 
404E61 [sys\system.pas][System][[email protected]][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 ’ | 

我使用的是2007年德尔福和FastMM 4.97。

编辑1:我认为这里的主要问题是为什么Classes.StdWndProc调用Menus.TPopupList?在调试器内挖掘调用堆栈显示System.FinalizeUnit被调用了三次,然后进入SysUtils.ShowException,它试图显示MessageBox,在一大堆user32.dll调用之后,我们最终返回到classes.StdWndProc。

编辑2:我有接口的问题,修复,使这个问题消失。带有接口的对象被释放,但是引用稍后被释放。当界面被释放时,发生了一个我最初忽略的异常。释放界面可能会损坏导致所有其他问题的东西。

回答

2

确保FastMM4是项目文件使用条款(项目|查看源代码)中的第一行。如果它不存在,然后添加它。

2

在Menus.pas完成后,您的某个表单看起来正在遭到破坏。如果您的表单上有菜单,则可能必须在其使用列表中的接口部分中使用菜单,这应该使其成为不可能。

我唯一一次看到像这样的问题弹出(没有双关语意图)是使用包时。你可能使用带插件的DPK来添加一个弹出菜单或菜单项到你的程序中吗?如果你不小心,程序包定制可以为你的程序做一些奇怪的事情。

无论采用哪种方式,解决方案都可能是在menus.pas定稿前自行处理菜单。当程序关闭的时候,在弹出菜单中调用Free并查看是否可以解决问题。

+0

是的,这就是问题的关键,为什么menus.pas在所有表格完成之前为时过早地完成。 我不确定包装,我认为应该没有那种,但我必须检查。 – Harriv 2010-03-26 20:38:55

3

我以前见过这样的问题。有时编译器会感到困惑,并产生不正确的初始化或终结顺序。可悲的是,我从来没有能够创建一个可复制的测试案例发送给CodeGear/Embarcadero人员。

每当发生这种情况,一个完整的重建帮助。

7

当一个单位在它间接依赖的另一个单元之后完成时,可能会出现这种情况。

对于为例,采取以下单元:

unit Unit1; 
interface 
uses 
    Contnrs; 

var 
    ItemHolder : TObjectList; 

implementation 

initialization 
    ItemHolder := TObjectList.Create(True); 
finalization 
    ItemHolder.Free; 
end. 

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

这就是为什么你需要非常小心你在最终化部分做了什么。

我不确定它是你的问题的根源,但我会先找那种方式。

0

更新:这只是部分工作

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

finalization 
    FreeAndNil(PopupList); 
end. 

这个自由PopupList并设为零,所以PopupList.Free在menus.pas会好。