Delphi中函数内部的内存泄漏

伊卡罗

我在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显示泄漏。如果不正确,为什么要释放此对象正确呢?

附言 我无法在创建对象之前将其释放,也无法将其释放到列表中;如果在将其添加到列表后立即释放它,则列表中的指针将为nil。

谢谢。

上面的代码是一个示例,实际代码是:

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  .
亚历克斯

组件具有所有者,以简化管理其内存的过程。

当使用Owner组件创建一个组件时(这意味着构造函数的参数Owner不是nil),会将这样的组件添加到owner组件的一个列表中(属性TComponent.Components)。从这一刻起,程序员就不必在意释放刚刚创建的组件,因为当所有者本身被释放时,它的所有者将释放它。

在没有所有者的情况下创建组件时,程序员有责任在某个时候显式释放它。

因此,您发现的有关内存泄漏的肯定是正确的,但可以用“只要AOwner不是nil来补充

如果您的代码中有关某个组件的泄漏,是因为所有者组件没有被释放,因此所有拥有的组件也不会被释放。在这种情况下,您必须查看所有者组件而不是所有者组件的生命周期中的错误。

本文收集自互联网,转载请注明来源。

如有侵权,请联系 [email protected] 删除。

编辑于
0

我来说两句

0 条评论
登录 后参与评论

相关文章