2017-10-03 5 views
0

전체 디버그 모드에서 FastMM을 사용하여 응용 프로그램에서 메모리 누출 문제를 해결하려고하면 TForm의 (하위 항목) 인스턴스에 대한 일부 누수가보고됩니다. 코드를 확인하고 단계별로 진행 한 결과, 이고 이 아닌 것으로 확인할 수 있습니다. Release에서 예정된 실제 해제가 발생하기 전에 FastMM이 누출 여부를 확인하는 것처럼 보입니다.델파이 양식을 올바르게 해제하는 방법

MyForm: TForm; 
MyForm := TForm.Create(nil); 
... 
MyForm.Release; // FastMM reports MyForm as a leak 

나는 대신에게 그들을 자유롭게 시도하지, 그 메모리 누수가보고 더 이상하지만, 해방 때 가끔 액세스 위반이 발생합니다

MyForm: TForm; 
MyForm := TForm.Create(nil); 
... 
MyForm.Free; // // FastMM does not report MyForm as a leak, but sometimes an access violation is triggered 

내가 그들을을 발표했는데, 즉시 Application.ProcessMessages를 호출합니다. 이해 한대로 Zoë Peterson의 대답을 https://stackoverflow.com/a/917187/1465896에서 읽을 수 있습니다. 이 Application.ProcessMessage를 항상 즉시 충돌 때문에 내가 잘못 이해해야합니다

MyForm: TForm; 
MyForm := TForm.Create(nil); 
... 
MyForm.Release; 
Application.ProcessMessages; // always triggers an access violation 

나는 그들이 메모리 누수 로그 파일을 혼란 이상의 개체를 포함하기 때문에, 기대 메모리 누수로 그 형태를 등록하지 않는, 더 중요한 누출을 찾기가 더 어려워졌습니다.

내 질문은 Delphi 양식을 적절하게 해제하여 FastMM이 누출로보고하지 않도록하는 방법입니다. (I 프로젝트를 게시하는 방법을 모르기 때문에,) 예와 같이 포함 된 짧은, 자기, 수정 (에 Compilable되지 않음)

요청으로

는 여기 SSCnCE입니다 :

파일 FormRelease.dpr :

program FormRelease; 

uses 
    FastMM4 in 'FastMM4.pas', 
    Vcl.Forms, 
    MainForm_fm in 'MainForm_fm.pas' {MainForm}, 
    MyForm_fm in 'MyForm_fm.pas' {MyForm}; 

{$R *.res} 

begin 
    Application.Initialize; 
    Application.MainFormOnTaskbar := True; 
    Application.CreateForm(TMainForm, MainForm); 
    Application.Run; 
end. 

파일 MainForm_fm.pas :

unit MainForm_fm; 

interface 

uses 
    Vcl.Forms, 
    MyForm_fm; 

type 
    TMainForm = class(TForm) 
    procedure FormCreate(Sender: TObject); 
    procedure FormDestroy(Sender: TObject); 

    private 
    FMyForm: TMyForm; 
    end; 

var 
    MainForm: TMainForm; 

implementation 

{$R *.dfm} 

procedure TMainForm.FormCreate(Sender: TObject); 
begin 
    FMyForm := TMyForm.Create(nil); 
end; 

procedure TMainForm.FormDestroy(Sender: TObject); 
begin 
    FMyForm.Release; 
end; 

end. 

파일 MyForm_fm.pas :

파일 FormRelease_MemoryManager_EventLog.txt에서이

발췌, 프로그램을 시작하고 ALT-F4로를 중지 한 후 :

This application has leaked memory. The small block leaks are (excluding expected leaks registered by pointer): 

13 - 20 bytes: TList x 1, Unknown x 1 
21 - 36 bytes: TPen x 1, TMargins x 1, TPadding x 1, TIconImage x 1, TBrush x 2, TTouchManager x 1, TSizeConstraints x 1, UnicodeString x 1, Unknown x 3 
37 - 52 bytes: TGlassFrame x 1, TFont x 2 
53 - 68 bytes: TIcon x 1 
69 - 84 bytes: TControlScrollBar x 2 
101 - 116 bytes: TControlCanvas x 1 
149 - 164 bytes: Unknown x 1 
917 - 1012 bytes: TMyForm x 1 

이유가 TMyForm x 1FMyForm.Release에 게시 된 CM_RELEASE가 처리 된 경우 왼쪽?

+1

나는 연결된 대답이 Application.ProcessMessages를 직접 홍보하지 않는다고 생각합니다. Release가 사용될 때 결과 메시지가 처리 될 것이라고 명시되어 있습니다.양식을 작성하고 파기하는 데 사용하는 코드를 분석 할 수 있습니까? 그것은 모든 응답자에게 중요합니다. – nil

+0

Release 직후에 Application.ProcessMessages를 호출하는 것은 기본적으로 Free를 호출하는 것과 동일해야합니다. 연기 할 것이없고, 출시는 무엇입니까. Form 자체의 이벤트 처리기에서이 작업을 수행하고 있습니까? 그러면 액세스 위반이 설명됩니다. – nil

+0

@Nil 이벤트 처리기에서 처리하지 않고 일반 소멸자 및 'finalization'섹션 (수정해야하는 응용 프로그램은 다소 특이한 구조를 가짐)에서 처리합니다. – Papaya

답변

1

두 개의 별개로 들립니다.

먼저 명시 적으로 양식을 작성하므로 명시 적으로 해제해야합니다. 고유 한 이벤트 핸들러 중 하나에서 자신을 자유롭게하는 것과 같은 특별한 경우를 제외하고는 Release를 호출 할 필요가 없습니다.

MyForm: TForm; 
... 
MyForm := TForm.Create(nil); 
try 
    // Only reference MyForm in this block 
finally 
    MyForm.Free; 
end; 

두 번째로, Free를 호출해도 문제가 발생하지 않습니다. 나는 그것을 드러내고 있다고 생각한다. 추측하면 MyForm 또는 해당 구성 요소 중 하나가이 블록 외부에서 참조되므로 액세스 위반이 발생합니다. 디버거를 사용하여이 참조를 찾고 수정하십시오.

+0

동의 : 나는 명시 적으로'Release'를 이해한다. 즉, 즉시 처리하는 것을 제외하고는'Free'와 상당히 동일하다. 이벤트 핸들러가 작업하고있는 것을 해제하기 전에 작업을 끝내도록 허용한다. – Papaya

+0

무료로 문제를 일으키지 않는 것에 대해, 그렇습니다. 단지 그것을 드러 낼 수 있습니다. 그러나 내가 고칠 수있는 가끔 충돌이 있다면, 나는 결코있을 수 없을 것입니다. – Papaya

+0

양식의 생성 및 해제를 직접 제어하는 ​​경우에는 해당 범위 외부에서 액세스 할 수 없도록해야합니다. 양식을 전역 변수로 취급하려는 경우이를 양식으로 선언하고 소유자로 응용 프로그램을 지정하고 응용 프로그램을 종료 할 때 응용 프로그램에서 정리하도록 처리해야합니다. –