2. CGCIICho sanghyun’s Game Classes II
SEH 란 ?
SEH(Structured Exception Handling) 은 윈도즈 O/S 차원의 예외 처리 시스템이다 .
SEH 는 C++ Exception 과 별개이며 언어 중립적이다 .
(C++ 의 try, catch 에는 잡히지 않는다 .)
일반적으로 ‘뻑 !’ 났을 때 덤프 남기는 용도로 많이 사용한다 !!
보통 SEH 의 사용은 여기까지다 .
덤프 남기는 것만으로도 감사 감사 ~
Structured Exception Handling
예외처리
(Divide by zero, Access Violation at …! 등등 )
try
throw
catch
__try
__ exception
__finally
C++ Exception SEH
3. CGCIICho sanghyun’s Game Classes II
SHE 란 ?예외처리
하지만 C++ Exception 보장 처리와 SEH 를 연동 처리
하면 뻑이 나도 다운되지 않고 안전하게 동작 가능한 서버를
만들 수 있다 .
그렇다면 !
SEH 로 Windows System Exception 만
무모화 시킨다면 다운 없는 서버 !!!?
오히려 더 큰일난다 !
→ 예외 중립 훼손
( 즉 뻑 ! 났는지도 모르고 아무런 처리도 없이 그냥 넘기면 더 큰일남 )
4. CGCIICho sanghyun’s Game Classes II
SEH 와 C++ Exception 의 결합
Visual C++ 의 Project 의 Property 에서 /EHa 옵션을 설정한다 .
즉 C++ Exception 과 SEH 가 연동될 수 있도록 옵션을 설정한다 .
예외처리
5. CGCIICho sanghyun’s Game Classes II
SEH 사용 (1)
보통 뻑이 나면 Mini-Dump 를 남기는 용도로만 사용한다 .
void fSEHTranslator(unsigned int, LPEXCEPTION_POINTERS p_pException)
{
…
CreateDump(p_pException);
…
printf(“ 뻑났슈 !!! 코딩 이렇게 밖에 못해 ?!!”);
}
void main()
{
// 쓰레드마다 설정해 주어야 한다 .
_set_se_translator(&fSEHTranslator);
…
// 뻑 유발자 코드 ( 처리 중 뻑나면 fSEHTranslator 함수를 실행할 것이다 !)
*(int*)0 = 10;
}
void fSEHTranslator(unsigned int, LPEXCEPTION_POINTERS p_pException)
{
…
CreateDump(p_pException);
…
printf(“ 뻑났슈 !!! 코딩 이렇게 밖에 못해 ?!!”);
}
void main()
{
// 쓰레드마다 설정해 주어야 한다 .
_set_se_translator(&fSEHTranslator);
…
// 뻑 유발자 코드 ( 처리 중 뻑나면 fSEHTranslator 함수를 실행할 것이다 !)
*(int*)0 = 10;
}
예외처리
6. CGCIICho sanghyun’s Game Classes II
SEH 와 C++ 예외의 결합
void fSEHTranslator(unsigned int, LPEXCEPTION_POINTERS p_pException)
{
CreateDump(p_pException);
throw std::exception();
}
void main()
{
// 쓰레드마다 설정해 주어야 한다 .
_set_se_translator(&fSEHTranslator);
…
try
{
// 뻑 유발자 !! ( 처리 중 뻑나면 std::exception() 이 발생할 것이다 !!)
*(int*)0 = 10;
}
catch(…)
{
printf(“ 뻑났음 !”);
}
}
void fSEHTranslator(unsigned int, LPEXCEPTION_POINTERS p_pException)
{
CreateDump(p_pException);
throw std::exception();
}
void main()
{
// 쓰레드마다 설정해 주어야 한다 .
_set_se_translator(&fSEHTranslator);
…
try
{
// 뻑 유발자 !! ( 처리 중 뻑나면 std::exception() 이 발생할 것이다 !!)
*(int*)0 = 10;
}
catch(…)
{
printf(“ 뻑났음 !”);
}
}
2. C++ Exception 을 던진다 !!!!
3. 그럼 C++ Exception 이 여기서 튀어나온다 !!
4. 당연히 C++ Exception 은 여기에서 잡힌다 !
1. 여기서 ‘뻑’난다 !!!
( 이 순간 C++ Exception 이 발생하지 않고 SEH 에 의해 ...)
예외처리
C++ Exception 과 함께 사용하면 좀더 다른 처리가 가능하다 .
7. CGCIICho sanghyun’s Game Classes II
CGCII 예외 시스템
void CExecutorIOCP::Execute(DWORD p_tickWait)
{
// 쓰레드마다 설정해 주어야 한다 .
_set_se_translator(&fSEHTranslator);
while(m_bDone)
{
DWORD dwResult;
DWORD dwBytes;
ULONG_PTR pHKey;
LPOVERLAPPED pOverlapped;
dwResult = GetQueuedCompletionStatus(m_hCP, &dwBytes, &pHKey, &pOverlapped, p_tickWait);
ICGExecutable* pExecuable = static_cast<ICGExecutable*>(pOverlapped);
pExecutable->ProcessExecute(dwResult, dwBytes);
pExecutable->Release();
}
}
void CExecutorIOCP::Execute(DWORD p_tickWait)
{
// 쓰레드마다 설정해 주어야 한다 .
_set_se_translator(&fSEHTranslator);
while(m_bDone)
{
DWORD dwResult;
DWORD dwBytes;
ULONG_PTR pHKey;
LPOVERLAPPED pOverlapped;
dwResult = GetQueuedCompletionStatus(m_hCP, &dwBytes, &pHKey, &pOverlapped, p_tickWait);
ICGExecutable* pExecuable = static_cast<ICGExecutable*>(pOverlapped);
pExecutable->ProcessExecute(dwResult, dwBytes);
pExecutable->Release();
}
}
SEH 와 C++ Exception 이 결합한다면 ?
IOCP Executor 의 처리를 try-catch 문으로 처리한다 .
try
{
pExecutable->ProcessExecute(dwResult, dwBytes);
}
catch(…)
{
}
참고 ) 성능을 위해 while 문에 try-catch 문은 최대한 빼도록 구현함 . try-catch 문을 밖으로 빼고 이중 while 문을 쓰는 것이 일반적임 .
예외처리
만약 , 이 함수 실행 중 ‘뻑’이 났다면…
이 ProcessExecute() 함수가 Strong Exception Guarantee 를 제공
하는 함수라면…
try-catch 블록으로 감싼다 .
8. CGCIICho sanghyun’s Game Classes II
CGCII 예외 시스템
CGCII 의 모든 Engine 시스템의 실행 처리는 CGCII 의 Execute System 하에서
동작을 하며 완벽한 Strong Exception Guarantee 를 보장한다 .
쉽게 말해서 아래와 같이 동작한다 .
1. 예외발생 정보 저장 .
2. Mini Dump 남김 .
3. 예외 알림 .
예외처리
9. CGCIICho sanghyun’s Game Classes II
CGCII 예외 처리
Pairing 처리를 해주어야 하는 것 !! 들
예외처리
예를 들어 접속 처리 과정에서 OnConnect() 가 정상적으로 호출되었다면 반드시
OnDisconnect() 가 호출되어야 한다 .
OnEnter() 함수가 호출되었으면 반드시 OnLeave() 함수가 호출되어야 한다 .
객체에 예외처리 전달
- Message 의 처리 과정에서 Message 처리 도중 전달되는 객체에도 예외처리 권한이
주어져야 한다 .
기타 등등…
원하는 시기에 원하는 대상에 원하는 내용의 예외를 처리할 수 있는 구조를 지원해주어야 한다
.
10. CGCIICho sanghyun’s Game Classes II
강제 예외 발생
강제 예외 발생 (Force Rasing Exception) 이란 강제로 예외를 발생 시키는 것 .
‘ 데드락’이나 ‘무한루프’에 빠진 쓰레드에 강제로 예외를 발생시켜 해결할 수 있다 .
다만 ! 예외 안전이 처리되었을 때만 제대로 처리 가능하다 . 그렇지 않다면 예외 발생시켜봐
야 어차피 엉망진창된다 .
Managed C++ 에는 이런 기능 있지만 Native C++ 에서는 직접 만들어야 된다 .
강제 예외 발생 구현은 시간 및 공간 제한 상 생략 ~
예외처리
TLS를 사용하여 성능을 향상시킬 수 있다!!
아무리 Lock-Free라 해도 그냥 값을 복사하는 것보다는 성능이 확실히 떨어진다.
그래서 Lock의 최소화를 위해 TLS를 사용한다.
생성하려는 객체는 반드시 ICGPoolable&lt;T&gt;를 상속받아야 한다.
사용할 때는 그냥 Alloc()함수를 호출하면 되고…
사용이 끝나게 되면 Free()함수를 호출하면 되는데 일반적으로 OnFinalRelease()함수에서 해준다.
Windows의 기본 할당자와 CGPool의 성능을 비교한다.(Windows는 기본적으로 16Kbyte까지 LFH가 적용된다.)
Object Pool은 객체의 할당을 위한 Pool이다.
사용방법은 매우 간단하다!!!
첫째 CGPool::CObject&lt;T&gt; 라고 하면 된다~~
그러면 그냥 Alloc(), Free()함수를 사용하여 객체의 할당과 할당해제를 수행할 수 있다
Pool 객체의 대상이 되는 객체는 무조건 ICGPoolable&lt;T&gt;을 상속받아야만 한다!!!
그리고 참조계수로 관리되므로 OnFinalRelease에 delete this가 아니라 Free(this)가 호출되어야 한다.
즉 다 사용되면 지워지는 것이 아니라 풀로 되돌려지는 것이다.
생성하려는 객체는 반드시 ICGPoolable&lt;T&gt;를 상속받아야 한다.
사용할 때는 그냥 Alloc()함수를 호출하면 되고…
사용이 끝나게 되면 Free()함수를 호출하면 되는데 일반적으로 OnFinalRelease()함수에서 해준다.
Alloc()/Free()를 사용하고 또 매번 OnFinalRelease()를 호출하도록 하려면 귀찬다.
따라서 NCGPoolable을 지원해준다.
또 NCGPoolable&lt;T&gt;만 상속받았으면 NEW&lt;T&gt;로 생성한다면 자동으로 Pool에서 할당을 해준다.
또 NCGPoolable&lt;T&gt;만 상속받았으면 NEW&lt;T&gt;로 생성한다면 자동으로 Pool에서 할당을 해준다.