我在stackoverflow网站上发现这是肯定的:
“没有内存泄漏。
function TBaseForm.CreateEdit(AOwner: TWinControl;
inTop, inLeft, inWidth: integer) : TEdit;
begin
Result := TEdit.Create(AOwner);
Result.Parent := AOwner;
Result.Width := inWidth;
Result.Top := inTop;
Result.Left := inLeft;
end;
“
任何人都可以确认吗? FastMM在销毁此对象时显示泄漏。如果不是这样,那么为什么要释放这个对象是正确的呢?
聚苯乙烯。我之前无法创建对象并释放它以及对象进入列表,如果我在将其添加到列表后将其释放,则列表中的指针将为零。
感谢。
上面的代码是真实代码的示例:
procedure TtvdEventCenter.tvdRegister(const AObject: TComponent; const AEvent: string; const ACallback: TtvdEventDetailedCallback);
var
aItem: TtvdEventObserver;
begin
aItem := tvdAddObserver(AObject, AEvent);
aItem.FtvdDetailedCallback := ACallback;
end;
function TtvdEventCenter.tvdAddObserver(const AObject: TComponent; const AEvent: string): TtvdEventObserver;
begin
Assert(AObject <> nil);
Assert(AEvent <> '');
Result := TtvdEventObserver.Create(Self);
Result.FtvdObject := AObject;
Result.FtvdEvent := AEvent;
AObject.FreeNotification(Self);
FtvdList.Add(Result);
end;
FastMM结果
A memory block has been leaked. The size is: 20
This block was allocated by thread 0x2A00, and the stack trace (return addresses) at the time was:
404D79 [System.pas][System][@ReallocMem][3935]
452971 [Classes.pas][Classes][TList.SetCapacity][3777]
4526FC [Classes.pas][Classes][TList.Grow][3615]
4524B1 [Classes.pas][Classes][TList.Add][3514]
45FBFB [Classes][TComponent.FreeNotification]
78EA83 [uTvdEventCenter.pas][uTvdEventCenter][TtvdEventCenter.tvdAddObserver][120]
78EE45 [uTvdEventCenter.pas][uTvdEventCenter][TtvdEventCenter.tvdRegister][169]
14D0308 [uTvdParisLiteAlertCenter.pas][uTvdParisLiteAlertCenter][TtvdParisLiteAlertCenter.Create][448]
14CEBAC [uTvdParisLiteAlertCenter.pas][uTvdParisLiteAlertCenter][CreateStvdParisLiteAlertCenter][225]
14DD142 [uTvdParisLiteMainPanel.pas][uTvdParisLiteMainPanel][TtvdParisLiteMainPanel.tvdSetupNonVisualComponents][2315]
14E0E67 [uTvdParisLiteMainPanel.pas][uTvdParisLiteMainPanel][TtvdParisLiteMainPanel.tvdSetup][2660]
The block is currently used for an object of class: Unknown
The allocation number is: 102890
Current memory dump of 256 bytes starting at pointer address 7E64B5F0:
B0 69 79 7E 80 80 80 80 80 80 80 80 80 80 80 80 A2 7D B8 6F 80 80 80 80 00 00 00 00 D1 BE 64 7E
00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 2A A3 01 00 0A 4D 40 00 DB 7F 40 00 0C 82 40 00
C2 D4 56 00 28 8C 42 00 20 00 64 00 2E 00 44 00 20 00 64 00 2E 00 44 00 2E 00 44 00 2E 00 44 00
00 2A 00 00 00 2A 00 00 26 4D 40 00 95 80 40 00 C1 9C 40 00 09 9C 40 00 D3 64 40 00 16 64 40 00
25 6A 40 00 56 64 40 00 63 64 40 00 37 FF 48 00 07 2A 45 00 12 00 00 00 B0 04 02 00 59 8E 6D 84
60 92 5B 01 80 80 80 80 80 80 80 80 80 80 80 80 80 80 A6 71 92 7B 80 80 00 00 00 00 11 BB 64 7E
00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 4E A5 01 00 0A 4D 40 00 FF 63 40 00 DA 69 40 00
34 64 40 00 31 67 40 00 68 FC 45 00 3E FD 45 00 08 FB 45 00 9C 55 44 01 DF DE 44 01 34 0E 45 01
° i y ~ € € € € € € € € € € € € ¢ } ¸ o € € € € . . . . Ñ ¾ d ~
. . . . . . . . . . . . . . . . * £ . . . M @ . Û @ . . ‚ @ .
Â Ô V . ( Œ B . . d . . . D . . d . . . D . . . D . . . D .
. * . . . * . . & M @ . • € @ . Á œ @ . . œ @ . Ó d @ . . d @ .
% j @ . V d @ . c d @ . 7 ÿ H . . * E . . . . . ° . . . Y Ž m „
` ’ [ . € € € € € € € € € € € € € € ¦ q ’ { € € . . . . . » d ~
. . . . . . . . . . . . . . . . N ¥ . . . M @ . ÿ c @ . Ú i @ .
4 d @ . 1 g @ . h ü E . > ý E . . û E . œ U D . ß Þ D . 4 . E .
同样的事情发生在这个(更简单的)
function TtvdAvlWelfareMenu.AddMenuItem(const aCaption: string; aTag: Integer; aEvent: TNotifyEvent): TMenuItem;
begin
Result := TMenuItem.Create(Self);
Result.Caption := aCaption;
Result.Tag := aTag;
Result.OnClick := aEvent;
Items.Add(Result);
end;
A memory block has been leaked. The size is: 20
This block was allocated by thread 0x2BCC, and the stack trace (return addresses) at the time was:
404D0A [System.pas][System][@GetMem][3693]
4063FF [System.pas][System][TObject.NewInstance][11044]
4069DA [System.pas][System][@ClassCreate][12121]
406434 [System.pas][System][TObject.Create][11059]
4BFFE8 [Menus.pas][Menus][UniqueCommand][695]
4C0558 [Menus.pas][Menus][TMenuItem.Create][941]
129649A [utvdParisLiteAVLWelfarePopupMenu.pas][utvdParisLiteAVLWelfarePopupMenu][TtvdAvlWelfareMenu.AddMenuItem][183]
1295EFD [utvdParisLiteAVLWelfarePopupMenu.pas][utvdParisLiteAVLWelfarePopupMenu][TtvdAvlWelfareMenu.Create][123]
14DDED5 [uTvdParisLiteMainPanel.pas][uTvdParisLiteMainPanel][TtvdParisLiteMainPanel.tvdSetupUnitPopupMenu][2501]
14DE1C5 [uTvdParisLiteMainPanel.pas][uTvdParisLiteMainPanel][TtvdParisLiteMainPanel.tvdSetupVisualComponents][2569]
14E0F03 [uTvdParisLiteMainPanel.pas][uTvdParisLiteMainPanel][TtvdParisLiteMainPanel.tvdSetup][2661]
The block is currently used for an object of class: TChangeLink
The allocation number is: 109793
Current memory dump of 256 bytes starting at pointer address 7E63B0B0:
30 9A 4B 00 00 00 00 00 24 42 4C 00 B0 A0 67 7E 00 00 00 00 A5 B8 35 F3 00 00 00 00 F0 98 63 7E
00 00 00 00 00 00 00 00 88 2D 41 00 00 00 00 00 D0 AC 01 00 0A 4D 40 00 FF 63 40 00 DA 69 40 00
34 64 40 00 83 66 40 00 60 3A 4C 00 48 3C 4C 00 D4 64 29 01 58 5E 29 01 D5 DE 4D 01 C5 E1 4D 01
CC 2B 00 00 CC 2B 00 00 26 4D 40 00 FA 80 40 00 9C 28 44 01 FD 29 44 01 A3 24 44 01 B2 52 44 01
39 E7 44 01 20 53 46 01 DE D3 4D 01 FB 0E 4E 01 B7 F8 54 01 14 00 00 00 B0 04 02 00 83 75 7F 91
D0 60 44 00 60 29 63 7E 13 00 00 00 1C 00 00 00 00 00 00 00 7C 8A 80 6E 00 00 00 00 31 AB 63 7E
00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 F5 AB 01 00 79 4D 40 00 71 29 45 00 FC 26 45 00
B1 24 45 00 75 FC 45 00 3E FD 45 00 08 FB 45 00 FC FA 43 01 7A 0F 44 01 BF E4 44 01 5E 11 45 01
0 š K . . . . . $ B L . ° g ~ . . . . ¥ ¸ 5 ó . . . . ð ˜ c ~
. . . . . . . . ˆ - A . . . . . Ð ¬ . . . M @ . ÿ c @ . Ú i @ .
4 d @ . ƒ f @ . ` : L . H < L . Ô d ) . X ^ ) . Õ Þ M . Å á M .
Ì + . . Ì + . . & M @ . ú € @ . œ ( D . ý ) D . £ $ D . ² R D .
9 ç D . S F . Þ Ó M . û . N . · ø T . . . . . ° . . . ƒ u ‘
Ð ` D . ` ) c ~ . . . . . . . . . . . . | Š € n . . . . 1 « c ~
. . . . . . . . . . . . . . . . õ « . . y M @ . q ) E . ü & E .
± $ E . u ü E . > ý E . . û E . ü ú C . z . D . ¿ ä D . ^ . E .
答案 0 :(得分:3)
组件拥有所有者,以简化管理内存的过程。
使用Owner组件创建组件时(这意味着构造函数的参数Owner
不是nil
),这样的组件将添加到owner组件的列表中(property { {1}})。从这一刻开始,程序员不需要关心释放刚创建的组件,因为它的所有者将在释放所有者本身时释放它。
在没有所有者的情况下创建组件时,程序员有责任在某个时刻明确释放它。
因此,您发现的内存泄漏肯定是正确的,但只要TComponent.Components
不是AOwner
“就可以用补充。
如果您的代码中有关于组件的泄漏,那是因为没有释放所有者组件,因此也没有自有组件也是免费的。在这种情况下,您必须查看所有者组件生命周期中的错误,而不是拥有的组件。
答案 1 :(得分:0)
当AObject.FreeNotification(Self)
的内部组件列表在AObject
被释放时通知时,报告的内存泄漏是在AObject
调用内部分配的。由于该列表被泄露,因此AObject
永远不会被释放。在这种情况下,FastMM也应报告用于AObject
本身的内存泄漏。
AObject
到底代表什么?它在哪里以及如何创建?
在您的第二个示例中,跟踪表明TMenuItem
正在泄漏,因为没有释放拥有TtvdAvlWelfareMenu
。
所以你显然没有正确管理你的对象。但是你没有显示任何代码,所以没有办法诊断原因。