2014-01-23 3 views
0

Я нахожу это утвердительный здесь на сайте StackOverflow:утечка памяти внутри функции в Delphi

«Там нет утечки памяти

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 обнаруживает утечку при уничтожении этого объекта. Если это не так, как правильно было бы освободить этот объект?

Ps. Я не могу создать объект раньше и освободить его, а также объект входит в список, и если я освобожу его сразу после добавления его в список, указатель в списке будет равен нулю.

Спасибо.

Код выше образец реальный код:

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 . 
+2

В этой функции отсутствует утечка памяти, если «AOwner» - это элемент управления, который в какой-то момент вашего приложения уничтожается. – TLama

+1

Что конкретно говорит FastMM? – Blorgbeard

+0

Итак, из того, что вы говорите, TLama - это то, что вместо использования Я как AOwner я должен создать глобальную переменную, которая будет владельцем всего созданного объекта, и когда я освобожу его в функции Destroy, все остальные объекты также будут уничтожены? – Icaro

ответ

3

Компоненты имеют владельца, чтобы упростить процесс управления своей памятью.

Когда компонент создается с компонентом владельца (что означает, то constructor's параметр Owner не nil), такой компонент добавлен в список в компоненте владельца (свойство TComponent.Components). С этого момента программисту не нужно заботиться о выпуске только что созданного компонента, так как его владелец освободит его, когда сам владелец будет освобожден.

Когда компонент создается без владельца, программист становится ответственным за его явное освобождение в какой-то момент.

Так, утвердительный об утечках памяти вы нашли правильный, но она может быть дополнена «до тех пор, как AOwner не nil».

Если в вашем коде содержится утечка относительно компонента, это связано с тем, что компонент владельца не освобождается, поэтому никакие принадлежащие ему компоненты также не будут свободны. В этом случае вам придется искать ошибку в жизненном цикле владельца компонента, а не в принадлежащем ему компоненте.

0

Сообщаемая память, просочившаяся, выделяется внутри вызова AObject.FreeNotification(Self) при росте внутреннего списка компонентов AObject, чтобы уведомить, когда AObject освобожден. Поскольку этот список просочился, то понятно, что AObject никогда не освобождается. В этом случае FastMM также должен сообщать об утечке памяти, также используемой для AObject.

Что именно представляет AObject? Где и как оно создается?

В вашем втором примере след предполагает, что утечка TMenuItem, так как владение TtvdAvlWelfareMenu не освобождается.

Таким образом, вы явно не управляете своими объектами правильно. Но вы не указали какой-либо из этого кода, поэтому нет возможности диагностировать причину.

+0

AObject является самообслуживанием от устройства, вызывающего для регистрации в Event Center, например: StvdEventCenter.tvdRegister (Self, FtvdEvent, CallbackEvent) – Icaro

+0

Это не отвечает на мои вопросы о том, что этот объект на самом деле, как создается этот объект, как/если этот объект освобожден и т. д. –

+0

Я понимаю, что эта функция «function TtvdEventCenter.tvdAddObserver (const AObject: TComponent; const AEvent: string): TtvdEventObserver;" вызов этой функции "функция TtvdEventCenter.tvdAddObserver (const AObject: TComponent; const AEvent: string): TtvdEventObserver;" который вызван «StvdEventCenter.tvdRegister (Self, FtvdEvent, CallbackEvent)», поэтому AObject = Self, где self является объектом, который регистрируется в службе, и да, он освобожден. Извините, может быть, я что-то упустил в вашем вопросе. – Icaro

Смежные вопросы