Development Technology Seminar 작 성 자 : 고형호 이 메 일 : hyungho.ko@gmail.com 최초작성일 : 2007.01.19 최종작성일 : 2007.02.05 버 전 : 01.05 홈 피 : www.innosigma.com
Goal Exception Handling
1. SEH vs. CEH
Exception Handling (1/2) Exception Handling SEH(Structured Exception Handling) -. 운영체제가제공하는기법. -. 메모리액세스침해, 스택오버플로우, 0으로나누기등과같이저급의문제 -. try, except, finally CEH(C++ Exception Handling) -. C++ 언어가제공하는기법 -. C++ 언어의일부분으로, 애플로케이션코드에서의문제 -. try, catch, throw
Exception Handling (2/2) CEH(C++ Exception Handling) 동기화 (Synchronous) -. 컴파일러는명확한 throw 문으로만예외를던질수있다. -. 컴파일러는객체의수명을추적할필요없다. 비동기화 (Asynchronous) -. 컴파일러는 throw 문없이도예외를던질수있다. -. 컴파일러는객체의수명을추적해야하고코드의어느시점에서예외를풀어줄수있게준비되어야한다.
Exception int _tmain(int argc, _TCHAR* argv[]) TCHAR* p = NULL; p[1] = _T('M'); return 0; [Project: 01_Crash] SEH try, except, finally HOW TO? CEH try, catch, throw
SEH vs. CEH SEH CEH int _tmain(int argc, _TCHAR* argv[]) try TCHAR* p = NULL; p[1] = _T('M'); except(exception_execute_handler) tcout << "Exception caught!" << endl; return 0; int _tmain(int argc, _TCHAR* argv[]) try TCHAR* p = NULL; p[1] = _T('M'); catch(...) tcout << "Exception caught!" << endl; return 0; [Project: 02_SEH] [Project: 03_CEH]
Exception 원인 int _tmain(int argc, _TCHAR* argv[]) TCHAR* p = NULL; p[1] = _T('M'); 메모리액세스침해 운영체제가처리하는저급의문제 SEH
C++ Exception Handling 동기화 (Synchronous) CEH 비동기화 (Asynchronous) CEH int _tmain(int argc, _TCHAR* argv[]) try TCHAR* p = NULL; p[1] = _T('M'); catch(...) tcout << "Exception caught!" << endl; return 0; int _tmain(int argc, _TCHAR* argv[]) try TCHAR* p = NULL; p[1] = _T('M'); catch(...) tcout << "Exception caught!" << endl; return 0; [Project: 03_CEH] [Project: 04_CEH_Asyn]
CEH Visual Studio 2005 Setting 동기화 (Synchronous) : /EHsc 비동기화 (Asynchronous) : /EHa
2. Exception Information
Exception Information (1/2) int _tmain(int argc, _TCHAR* argv[]) try TCHAR* p = NULL; p[1] = _T('M'); except(exception_execute_handler) tcout << _T("Exception caught!") << endl; DWORD dwexceptioncode = GetExceptionCode(); if (EXCEPTION_ACCESS_VIOLATION == dwexceptioncode) tcout << _T("Access violation!") << endl; return 0; [Project: 05_SEH_Info]
Exception Information (2/2) int _tmain(int argc, _TCHAR* argv[]) try TCHAR* p = NULL; p[1] = _T('M'); catch(...) tcout << _T("Exception caught!") << endl; DWORD dwexceptioncode = GetExceptionCode(); if (EXCEPTION_ACCESS_VIOLATION == dwexceptioncode) tcout << _T("Access violation!") << endl; return 0; [Project: 06_CEH_Info] error C2707: '_exception_code' : 내장함수의컨텍스트가잘못되었습니다. except 블록또는예외필터외부의 _exception_code() 즉, GetExceptionCode 는 SEH 예외필터와예외핸들러에서만사용가능하다.
Combining SEH and CEH (1/3) CEH 에서 SEH 정보를얻기위해서는 SEH 를 CEH 에의해다룰수있어야한다. SEH 가발생할때마다변환함수가호출되어적절한 CEH 가발생하도록변환한다. _se_translator_function _set_se_translator( _se_translator_function); typedef void (*_se_translator_function)( unsigned int ncode, struct _EXCEPTION_POINTERS* pexp); Exception Information
Combining SEH and CEH (2/3) void TransSEH(unsigned int ncode, struct _EXCEPTION_POINTERS* pexp) tcout << _T("In TransSEH") << endl; int _tmain(int argc, _TCHAR* argv[]) _set_se_translator(transseh); try TCHAR* p = NULL; p[1] = _T('M'); catch(...) tcout << _T("Exception caught!") << endl; return 0; [Project: 07_SEH_Translator]
Combining SEH and CEH (3/3) class ExceptionSEH public: ExceptionSEH(unsigned int ncode) : m_ncode(ncode) private: unsigned int m_ncode; public: void GetExceptionInfo() if (EXCEPTION_ACCESS_VIOLATION == m_ncode) tcout << _T("Access violation!") << endl; ; void TransSEH(unsigned int ncode, struct _EXCEPTION_POINTERS* pexp) tcout << _T("In TransSEH") << endl; throw new ExceptionSEH(nCode); int _tmain(int argc, _TCHAR* argv[]) _set_se_translator(transseh); try TCHAR* p = NULL; p[1] = _T('M'); catch(exceptionseh* pexp) tcout << _T("SEH Exception caught!") << endl; pexp->getexceptioninfo(); delete pexp; return 0; [Project: 08_SEH_Translator_Class]
3. Unhandled Exception
Unhandled Exception (1/9) 언제데이터를수집할까요? 어떤데이터를수집할까요?
Unhandled Exception (2/9) 언제데이터를수집할까요? LPTOP_LEVEL_EXCEPTION_FILTER SetUnhandledExceptionFilter( LPTOP_LEVEL_EXCEPTION_FILTER lptoplevelexceptionfilter); 애플리케이션에대하여마지막 except 블록에서호출될함수에대한포인터이다.
Unhandled Exception (3/9) LONG TopExceptionFilter(LPEXCEPTION_POINTERS pexp) tcout << _T("In TopExceptionFilter") << endl; return EXCEPTION_EXECUTE_HANDLER; int _tmain(int argc, _TCHAR* argv[]) SetUnhandledExceptionFilter((LPTOP_LEVEL_EXCEPTION_FILTER)TopExceptionFilter); TCHAR* p = NULL; p[1] = _T('M'); return 0; [Project: 09_Unhandled]
Unhandled Exception (4/9) 어떤데이터를수집할까요? DbgHelp.dll 파일의 MinidumpWriteDump API 를이용한 Dump 파일생성
Unhandled Exception (5/9) #include "dbghelp.h" typedef BOOL (WINAPI *MINIDUMPWRITEDUMP)(HANDLE hprocess, DWORD dwpid, ); LONG TopExceptionFilter(LPEXCEPTION_POINTERS pexp) tcout << _T("In TopExceptionFilter") << endl; LONG retval = EXCEPTION_CONTINUE_SEARCH; HMODULE hdll = ::LoadLibrary(_T("DbgHelp.dll")); MINIDUMPWRITEDUMP pdump = (MINIDUMPWRITEDUMP)::GetProcAddress(hDll, "MiniDumpWriteDump"); HANDLE hfile = ::CreateFile(_T("Crash.dmp"), GENERIC_WRITE, FILE_SHARE_WRITE, NULL, CREATE_ALWAYS, FILE_ATTRIBUTE_NORMAL, NULL); int _tmain(int argc, _TCHAR* argv[]) SetUnhandledExceptionFilter((LPTOP_LEVEL_EXCEPTION_FILTER)TopExceptionFilter); _MINIDUMP_EXCEPTION_INFORMATION ExInfo; ExInfo.ThreadId = ::GetCurrentThreadId(); ExInfo.ExceptionPointers = pexp; ExInfo.ClientPointers = NULL; BOOL bok = pdump(getcurrentprocess(), GetCurrentProcessId(), hfile, MiniDumpNormal, &ExInfo, NULL, NULL); if (bok) tcout << "Saved dump file to Crash.dmp" << endl; retval = EXCEPTION_EXECUTE_HANDLER; ::CloseHandle(hFile); ::FreeLibrary(hDll); return retval; TCHAR* p = NULL; p[1] = _T('M'); return 0; [Project: 10_MiniDump]
Unhandled Exception (6/9) Exception 결과
Unhandled Exception (7/9) Visual Studio 2005 프로젝트를이용하여덤프파일 (.dmp) 열기
Unhandled Exception (8/9) 덤프프로젝트 Debugging
Unhandled Exception (9/9) Visual Studio 2005 Debugging 정보를이용하여 Exception 원인을파악할수있게된다.
Visual C++ 6.0 PDB Setting (1/3) PDB(Program Debug Database) 파일만들기 Visual Studio 2005 컴파일러기본 release 옵션은 PDB 파일을생성한다. Visual C++ 6.0 컴파일러기본 release 옵션은 PDB 파일을생성하지않는다.
Visual C++ 6.0 PDB Setting (2/3)
Visual C++ 6.0 PDB Setting (3/3)
Summary Exception Handling SEH(Structured Exception Handling) CEH(C++ Exception Handling) 동기화 (Synchronous) : /EHsc 비동기화 (Asynchronous) : /EHa Win32 API _set_se_translator SetUnhandledExceptionFilter MinidumpWriteDump
4. Component
Unhandled Exception Component Client DIP SRP <<interface>> IBlackBox +Install() OCP void BlackBox::Install() SetUnhandledExceptionFilter( ); BlackBox +Install() SRP(Single Responsibility Principle) : 단일책임의원칙 DIP(Dependency Inversion Principle) : 의존관계역전의원칙 ISP(Interface Segregation Principle) : 인터페이스분리의원칙 LSP(Liskov Substitution Principle) : 리스코프대체원칙 OCP(Open-Closed Principle) : 개방폐쇄원칙
5. Utility
Userdump 8.1 (1/3) 관련문서 : http://support.microsoft.com/kb/241215 다운로드 : http://www.microsoft.com/downloads/ details.aspx?familyid=e089ca41-6a87-40c8-bf69-28ac08570b7e&displaylang=en
Userdump 8.1 (2/3) Monitor Program 예외가발생하여종료되거나더이상응답하지않는프로그램등록
Userdump 8.1 (3/3) Output Folder Exception Codes MiniDump