2. • SHE(구조적 예외처리)를 사용한다고 해서 코드 내에서 발생할 가능성이 있는 에러를 모두
무시할 수는 없지만, 에러 처리를 위한 사소한 작업으로부터 주요 작업을 분리할 수 있다.
• SEH를 사용하였을 때의 문제는 운영체제보다 컴파일러가 더 자주 문제를 야기한다.
SHE 를 사용하면 컴파일러는 예외 블록 내로 진입하고 빠져나갈 때마다 특수한 코드를
생성해야 하며, SEH를 위해 필요한 데이터 구조체를 지원하도록 테이블을 생성해야 한다.
• 컴파일러는 또한 예외 블록들 사이를 오갈 수 있도록 운영체제가 호출할 수 있는 콜백함수를
지원해야 한다.
• 하지만 개발자는 컴파일러가 제공하는 SHE 기능을 사용할 수 있기만 하면 된다.
• SHE는 종료 처리와 예외 처리라는 두 가지 주요 기능으로 구성되어 있으며, 이번 장에서는
종료 처리에 대해 알아본다.
3. 1. 예제를 통한 종료 처리기의 이해
예제에서 주석에 포함되어 있는 숫자는 코드의 수행 순서를
의미한다.
해당 예제에서 try – finally를 사용하는 것은 그다지 유용해
보이지 않는다.
이 코드는 세마포어를 획득하여 보호되고 있는 데이터의
내용을 변경한 후 새로운 값을 dwTemp 라는 지역변수에
저장한다.
이후 세마포어를 해제하고 호출자에게 새로운 값을
반환한다.
4. 1. 예제를 통한 종료 처리기의 이해
try 블록 마지막에 return 문장을 추가하였다.
return 문장이 바로 수행되면 이 스레드는 세마포어를
해제하지 않기 때문에 다른 스레드 가 세마포어에 대한
제어권을 획득할 수 없게 된다.
이러한 순서대로 코드가 수행되면 세마포어를 대기하는
다른 스레드가 절대로 수행을 재개할 수 없는 상황이 되기
때문에 아주 큰 문제를 야기하게 된다.
종료 처리기를 사용하면 이러한 문제를 피할 수 있다.
컴파일 러는 try 블록 내의 return 문장에 의해 함수를
빠져나가기 전에 finally 블록 내의 코드가 반드시 수행될 수
있도록 코드를 생성한다.
Funcenstein2 의 경우 종료 처리기에서 ReleaseSemaphore
함수를 호출하도록 하여 세마포어가 항상 해제될 수 있도록
하고 있다.
5. 1. 예제를 통한 종료 처리기의 이해
이렇게 코드를작성하면 스레드가 세마포어를 해제하지
않아서 세마포어를 기다리는 다른 스레드들이 CPU 시간을
부여받지 못하는 일은 절대로 발생하지 않을 것이다.
Finally 블록에 있는 코드들은 try 블록 내에서 함수가
반환되기 때문에 절대 수행되지 않는다.
따라서 이 함수의 반환 값은 9가 아닌 5가 된다.
컴파일러가 코드를 분석하는 과정에서 try 블록 내에 return
문장이 포함되어 있음을 확인한 경우, 반환 값을 컴파일러가
생성하는 임시변수에 저장하도록 코드를 생성하고 finally
블록 내에 포함되어 있는 명령을 수행하도록 코드를
생성한다. 이를 로컬 언와인드라 한다.
Funcenstein2 의 경우 컴파일러는 추가적인 코드를
생성해야 하며 시스템은 추가된 코드를 수행해야 하므로
이보다 많은 비용이 필요하다.
6. 1. 예제를 통한 종료 처리기의 이해
Funcenstein3 에서는 컴파일러가 try 블록 내에서 goto
문장이 사용 되었음을 발견하고 finally 블록을 먼저 수행할
수 있도록 로컬 언와인드를 위한 코드를 생성한다.
하지만 finally 블록이 수행된 직후 ReturnValue 블록 이하가
수행되기때문에 try 혹은 finally 블록 내에서는 함수의
반환이 일어나지 않는다.
Try블록의 자연스러운 제어 흐름을 가로채어 finally 블록을
수행하기 때문에 애플리케이션을 수행하는 CPU에 따라
상당한 성능상의 불이익을 초래할 수도 있다.
8. 1. 예제를 통한 종료 처리기의 이해
첫 번째 Funcarama1 함수를 SEH 종료 처리기의 장점을
활용하여 재작성 한 코드.
이 코드의 장점은 함수의 모든 정리코드가 Finally 블록
한군데에 집중되어 있다는 것이다.
이 함수에 코드를 추가하려는 경우,
단순히 정리 코드를 finally 블록 내에 추가하기만 하면 되기
때문에 실패할 가능성이 있는 위치마다 정리 코드를 매번
추가할 필요가 없어지게 된다.
9. 1. 예제를 통한 종료 처리기의 이해
Funcarama 최종 개선안
try 블록 내에서는 가능한 한 return을 쓰지 않는 것이 좋다.
이를 위해 마이크로소프트는 C/C++ 컴파일러에 __leave
키워드를 추가하였다.
leave 키워드의 장점을 이용한 코드이다.