|
FormClose이벤트에서 Action=caFree 하면 자동으로 free됩니다.
즉 delete하실 필요가 없습니다.
그렇지만 님과 같이 delete하더라도 access voilation이 나지는 않는데....
좀 이상하네요
빈프로젝트에 Form 2개만 넣어서 테스트 해보십시요
그럼 에러가 없을것입니다.
무슨 다른곳에서 Error가 나는것 아닌가 생각합니다.
[추신]
<< OnClose에서 Action=caFree하고 또 delete하여도 Error가 나지 않는 이유 >>
( caFree메가니즘 )
아래는 TForm의 조상인 TCustomForm의
Close함수와 Release 함수, 그리고 CM_RELEASE메세지를 받아서 처리하는 함수의 VCL 코드입니다.
//--------------------------------------------------------------
procedure TCustomForm.CloseModal;
var
CloseAction: TCloseAction;
begin
try
CloseAction := caNone;
if CloseQuery then
begin
CloseAction := caHide;
DoClose(CloseAction); // OnClose이벤트 핸들러 호출
end;
case CloseAction of
caNone: ModalResult := 0;
caFree: Release; // CloseAction = caFree이면 Release호출
end;
except
ModalResult := 0;
Application.HandleException(Self);
end;
end;
//--------------------------------------------------------------
procedure TCustomForm.Release;
begin
PostMessage(Handle, CM_RELEASE, 0, 0); //이부분에서 바로 release하지 않고 PostMessage합니다.
end;
//--------------------------------------------------------------
procedure TCustomForm.CMRelease;
begin
Free; //이부분에서 진짜로 release됩니다.
end;
//--------------------------------------------------------------
그런데 TCustomForm.Release함수에서 SendMessage가 아니고 PostMessage 입니다.
즉 곧바로 RELEASE되는것이 아니라
현재 함수코드진행은 수행이 끝나고 즉 CloseModal함수가 끝나야 되구요
또한 ShowModal을 호출한곳에서 다음 코드가 있다면 그것이 수행이 끝날때까지
실제적으로 Handle은 release가 되지 않는것입니다.
님의 아래코드에서 delete가 호출된후에
다음 GetMessage가 호출되어야 CustomForm의 Handle이 CM_RELEASE 메세지를 받을수 있는데...
이미 delete에서 Handle이 없어졌으므로 CM_RELEASE 는 아무 의미가 없는 메세지가 되는것입니다.
아래와 같이 코딩하면 확실에 에러가 납니다.
void __fastcall TForm1::Button1Click(TObject *Sender)
{
Form2=new TForm2(this);
int rslt=Form2->ShowModal();
Application->ProcessMessages(); //이부분에서 CustomForm의 Handle이 CM_RELEASE 메세지를 받아 free됨
delete Form2; //이미 free된것을 또 다시 free하려고 함 --> 이경우 여기서 반드시 에러가 남
}
//---------------------------------------------------------------------------
왜냐하면 Application->ProcessMessages 함수에서
TCustomForm.Release 에서 PostMessage한 메세지를
GetMessage로 가져와서 처리하게때문입니다.
[참고]
Form2는 아마 전역 변수일것입니다.
님과 같이 코딩하실때는 가능하면
TForm2 *frm=new TForm2(this); //이렇게 포인터변수를 선언해서 쓰는것이 안전합니다.
말이 많이 길어졌네요
결론적으로
님이 적어주신 코드에서는 직접적인 에러의 원인이 없습니다.
하지만 Action=caFree 나 delete둘중 하나만 쓰세요
그럼...
땅주인 님이 쓰신 글 :
: 메인 윈도우에서 여는 서브 윈도우의 Close Event에서 가지고 있던 Resource를 자동 해제하려고 이렇게 썼습니다.
:
: void __fastcall TForm2::FormClose(TObject *Sender, TCloseAction &Action)
: {
: Action = caFree;
: }
:
: 근데, 메인 윈도우에서 Form2를 열고, 닫은 후에도 Form2의 변수 값에 접근할 수 있고,
: 그런데.. delete는 할 수 없고.. 이게 어찌된 영문 인 지?
:
: [ Main Window의 Button Event ]
:
: void __fastcall TForm1::Button1Click(TObject *Sender)
: {
: TForm2 *pForm = new TForm2(this);
:
: pForm->ShowModal(); // 모달 상자로 열었음.
:
: k =pForm->m_ikk; // Form2의 멤버에 접근이 가능함.
:
: delete pForm; // Access Violation나옴.
: }
:
: 변수값은 Access가능하고, Form를 delete할 때는 에러나고.. 속시원히 해결을 좀?
: Action = caFree이면 폼이 가지고 있던 모든 리소스도 해제되는 것 아닌가요?
:
: 그리고, 사실 다른 곳에서 썼던 스크립트는 위와 비슷한 코드인데.. delete pForm에서 전혀 에러를 내지
: 않고 잘 나갑니다. 가끔 프로그램이 Access Violation을 내는데..여긴 지 아닌 지는 잘 모르겠지만..
: 어쨌거나 잘 돌아가는 경우가 더 많다는 것이죠.. 좀 헷갈려서..... 속시원히 해결해 주실분 부탁해요..
:
: 감사합니다.
|