C++Builder Programming Forum
C++Builder  |  Delphi  |  FireMonkey  |  C/C++  |  Free Pascal  |  Firebird
볼랜드포럼 BorlandForum
 경고! 게시물 작성자의 사전 허락없는 메일주소 추출행위 절대 금지
C++빌더 포럼
Q & A
FAQ
팁&트릭
강좌/문서
자료실
컴포넌트/라이브러리
메신저 프로젝트
볼랜드포럼 홈
헤드라인 뉴스
IT 뉴스
공지사항
자유게시판
해피 브레이크
공동 프로젝트
구인/구직
회원 장터
건의사항
운영진 게시판
회원 메뉴
북마크
볼랜드포럼 광고 모집

C++빌더 팁&트릭
C++Builder Programming Tip&Tricks
[885] [Exception] 예외처리1 - Application.OnException 활용
장성호 [nasilso] 12628 읽음    2009-04-22 23:47
핸들링 하지 못한 에러 잡기

신이 아니고서야 프로그램에서 에러발생하지 않는경우는 없을것입니다.
try-catch  (delphi : try - except ) 로 에러를 잡아서 처리합니다만
생각지도 못한 곳에서 에러가 발생하는경우가 있을것입니다.
이런 경우어떻게 처리하십니까?

TApplication의 OnException이벤트 핸들러
Application객체에 보면 OnException이라는 이벤트 핸들러가 있습니다.

함수형태는 TExceptionEvent 형으로써  

델파이의 경우

   
  TExceptionEvent =  procedure  ( Sender:  TObject;  E:  Exception)  of  object ;      



C++Builder로 표현하면

typedef  void  __fastcall  ( __closure  * TExceptionEvent)   
                              ( System: : TObject*  Sender,  Sysutils: : Exception*  E) ;  


 

OnException이벤트 핸들러 호출하는 곳
이 Application.OnExcptiption은 Application.HandleException에서 호출해줍니다.

    
procedure  TApplication. HandleException( Sender:  TObject) ; 
begin 
   if  GetCapture <> 0 then  SendMessage( GetCapture,  WM_CANCELMODE,  0,  0) ; 
   if  ExceptObject is Exception then 
   begin 
     if  not  ( ExceptObject is EAbort)  then 
       if  Assigned( FOnException)  then   //이벤트 핸들러가 설정되어있는경우 호출해줌 
        FOnException ( Sender,  Exception( ExceptObject) ) 
       else 
        ShowException ( Exception( ExceptObject) ) ; 
   end  
    SysUtils . ShowException( ExceptObject,  ExceptAddr) ; 
end ;         
 


Application.HandleException을 호출하는곳

그럼 Application.HandleException은 어디서 호출해주냐면?

1) TCustomForm에서 예외 발생시 Application.HandleException을 호출합니다.

2) TWinControl의 MainWndProc에서 WindowProc를 호출해주고 예외가 발생하면
    Application.HandleException을 호출합니다.

3) TDragObject의 WndProc와 MainWndProc에서 예외발생시 Application.HandleException을 호출합니다.

4) TDataModule의 HandleCreateException 와 DoDestroy 에서 예죄발생시 호출합니다.

5) 기타 StdCtrls , ComCtrls , ExtCtrls 등의 각종 Control및 Component에서도 예외발생시 호출해주는 곳이 많습니다.
        Timer 또는 ADOConnection등의 Component에서도 호출합니다.


* 특이사항
  ; GraphicControl의 WndProc에서는  Application.HandleException 을 직접 호출하지는 않습니다.
    만약 GraphicControl의 WndProc에서 예외가 발생하면 해당 GraphicControl이 소속된 WinControl의 WindowProc에서 
     except가 잡혀서 거기서  Application.HandleException가 호출됩니다.

     => 이경우 GraphicControl의 이벤트 핸들러(MouseDown/Move/Up등)에서 예외가 발생하더라도
         Application.OnException으로 넘어오는 Sender가 GraphicControl이 아니라
         Parent인 WinControl이 Sender가 될것입니다.

  * TPopupMenu , TMenuItem에서 예외발생시 PopupList가 Application.HandleException을 호출한다.

  * Action은 Application.OnIdle에서 호출하므로 예외발생 객체도 모두 Application이 된다.




TApplication의 OnException 사용예
   ; 이제 이 이벤트 핸들러를 사용한 예제를 살펴 보겠습니다.

    
void  __fastcall  TForm1: : FormCreate( TObject * Sender) 
{ 
//TApplication은 TComponent를 상속받은 놈인데 Name이 정해지지 않은상태다
//(별로 쓸일이 없으니)
// Application에서 HandleException을 호출한경우
// Sender가 Application이되는데.. 이를 위해 이름을 정해줌
  Application->OnException = "TApplication";  


 //프로그램 시작시 Application->OnException 이벤트 핸들러를 걸어준다. 
  Application->OnException = AppException; 

} 
//--------------------------------------------------------------------------- 
void  __fastcall  TForm1: : AppException( System: : TObject*  Sender,  Sysutils: : Exception*  E) 
{ 
  String sObj = "" ; 
   if ( Sender) 
   { 
      if ( Sender->InheritsFrom( __classid( TControl) ) ) 
      { 
         TControl  * ctrl= ( TControl * ) Sender; 
          while ( ctrl) 
         { 
            sObj = ctrl->Name+ " -> " + sObj; 
            ctrl = ctrl->Parent; 
         } 
      } 
       else  if ( Sender->InheritsFrom( __classid( TComponent) ) ) 
      { 
        TComponent  * Comp= ( TComponent * ) Sender; 
         sObj = Comp->Name; 
          if ( Comp->Owner) 
         { 
           sObj = Comp->Owner->Name +  " -> " +  sObj; 
         } 
      } 
   } 

   String sExpMsg = sObj +  " Msg:"  + E->Message; 

    //Log를 저장하거나.. SaveLog .. 
    //필요에 따라 메세지를 뿌려준다. 
   E->Message = sExpMsg; 
  Application->ShowException ( E) ; 

} 
   



메인 쓰레드에서 GUI Component및 Control에서 발생하는 예외는
모두 Application.OnException에서 잡아서 확인할수 있습니다


코드에서 잡지 못한 예외는 Application.OnException으로 처리하기를 권합니다.


참 위 코드에서 TControl인 경우와 TComponent인경우 분리되어있는데..
   Timer같은경우 Component이지만 Control은 아니므로 Parent가 없기때문에 분리되어있습니다.
   TComponent를 상속받지 않은 Object는 Name을 알수 없으므로.. 따로 처리하지 않았구요



그럼..
Lyn [tohnokanna]   2009-04-23 10:38 X
전 신인듯... Hello World 짰는데 오류가없어요!
장성호 [nasilso]   2009-04-23 11:12 X
Lyn님은 워낙 똑똑하니까...
...
내 코드에 별문제가 없어도 얼마든지 에러가 발생할수 있지요
다른 프로그램에서 내 프로그램에 잘못된 메세지를 보내도 프로그램에서 에러발생 할 수 있습니다.
그리고 내가 원치않는 모듈이 프로그램에 load될수도 있죠
예를들어 네이트온메신져 켜두면 "NateOnHook40u.dll" 라는 dll이 프로그램에 load됩니다.
저렇게 프로그래머가 작성하지 않는, 예기치 않는 모듈에서 예외가 얼마든지 발생할수도 있죠
문론 "NateOnHook40u.dll"모듈에서 예외가 발생하더라도 Applcation.OnException으로 들어오진 않겠지만...

김태선 [cppbuilder]   2009-04-23 14:24 X
예외처리에 대한 시리즈 강좌, 좋으네요.

수고가 많으십니다. ^^;

+ -

관련 글 리스트
885 [Exception] 예외처리1 - Application.OnException 활용 장성호 12628 2009/04/22
Google
Copyright © 1999-2015, borlandforum.com. All right reserved.