我使用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被调用三次,然后它会转到SysUtils.ShowException,它会尝试显示MessageBox,在一堆user32.dll调用之后我们最终会遇到classes.StdWndProc。
Edit2:我遇到了界面问题,修复了这个问题。已释放具有接口的对象,但稍后将发布该引用。当接口被释放时,发生了一个我最初以某种方式忽略的异常。释放界面可能会损坏导致所有其他问题的东西。
答案 0 :(得分: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。如果在关闭应用程序时仍有一些表单,TObjectList(因为它拥有该对象)将释放它包含的项目(Call TForm.Free)。但由于Unit1不依赖于TForm,因此单元Forms可能已经完成并且TForm.Destroy不再存在于内存中。
这就是为什么你需要非常小心你在终结部分做什么。
我不确定这是你问题的根源,但我会先这样看。
答案 1 :(得分:3)
之前我见过Delphi 2007的这些问题。有时编译器会混淆并生成不正确的初始化或完成顺序。遗憾的是,我从来没有能够创建一个可重现的测试用例来发送给CodeGear / Embarcadero人。
每当发生这种情况时,完全重建会有所帮助。
答案 2 :(得分:2)
确保FastMM4是项目文件的uses子句(项目|查看源代码)中的第一行。如果不存在,则添加它。
答案 3 :(得分:2)
在Menus.pas完成后,看起来你的一个表单会被破坏。如果您的表单上有菜单,则可能必须在界面部分的使用列表中设置菜单,这样就无法实现。
我唯一一次看到这样的问题弹出(没有双关语)是在使用包时。您是否正在使用具有插件的DPK,该插件可为您的程序添加弹出菜单或菜单项?如果您不小心,程序包最终化可以为您的程序做一些奇怪的事情。
无论哪种方式,解决方案可能是在menus.pas结束之前自己处理菜单。当程序关闭时,在弹出菜单上调用Free,看看是否能解决问题。
答案 4 :(得分:0)
更新:这只是部分解决方法
解决方法: 在您的应用程序的主要形式写
finalization
FreeAndNil(PopupList);
end.
这个免费的PopupList并设置为nil,所以在menus.pas中的PopupList.Free就可以了。