Windows 에러 핸들링
대부분의 Windows 함수가 사용하고 있는 반환 자료형은 아래의 표와 같다.
자료형 | 실패 했을 때의 값 |
---|---|
VOID |
이 함수는 절대 실패하지 않는다. 소수의 윈도우 함수만이 VOID 반환 자료형을 가짐 |
BOOL |
함수가 실패하면 0을 반환, 성공시에는 0이 아닌 값을 반환한다. 즉, 비교시 TRUE와 비교하는 것보단, FALSE와 비교하는것이 나음 |
HANDLE |
실패시 대개 NULL을 반환. 성공시 유효한 오브젝트 핸들을 반환한다. 몇몇 함수들은 -1로 정의된 INVALID HANDLE VALUE도 있기 때문에 주의 요망. SDK 문서에 명확하게 기술되어 있음 |
PVOID |
함수가 실패하면 NULL을 반환, 성공시 PVOID가 데이터를 저장하고 있는 메모리 주소를 가르킴 |
LONG/DWORD |
상당히 까다로운 형태이다. 대개 개수를 반환하나 어떤 이유로 인해 개수를 반환하지 못하면 0이나 -1을 반환한다. 이 반환형의 함수를 사용할 경우 플랫폼 SDK 문서를 주의깊게 살펴보길 바람 |
함수 호출 실패 원인 찾기
함수가 실패하면 왜 실패했는지 알아내야 하는데 이 때, GetLastError 함수를 사용할 수 있다.
GetLastError 함수를 통해 MS는 발생할 가능성이 있는 모든 에러 코드를 32bit의 숫자로 정의해 두었다.
함수의 형태는 다음과 같다.
DWORD GetLastError();
윈도우 함수가 실패할 경우, 내부적으로 함수를 호출한 스레드의 스레드 지역 저장소(thread-local storage)에 적절한 에러코드를 저장해둔다. 이러한 메커니즘을 통해 멀티 스레드에서 동시에 수행 된 경우라도 상호간의 영향을
미치지 않고 각 스레드별로 에러 코드를 유지할 수 있다.
따라서, GetLastError가 하는 일은 단순히 가장 최근에 호출된 함수의 에러코드를 스레드 지역 저장소로부터 가져오는 것이다.
WinError.h 헤더 파일은 MS가 정의한 모든 에러코드의 리스트를 가지고 있다.
다음은 WinError.h의 일부를 발췌한 것이며 이 파일은 약 39,000행을 넘는다.
#define ERROR_SUCCESS 0L
#define NOERROR 0L
#define ERROR_INVALID_FUNCTION 1L
#define ERROR_FILE_NOT_FOUND 2L
#define ERROR_PATH_NOT_FOUND 3L
#define ERROR_TOO_MANY_OPEN_FILES 4L
함수를 실패하게 되면 지체없이 GetLastError를 호출해야한다. 만약 GetLastError를 호출하기 전에 다른 함수를 호출하게 되면 수행 결과가 덮어 써지게 된다.
함수 호출이 성공하면 ERROR_SUCCESS를 ERROR 코드로 기록한다.
함수 호출 성공 이유 찾기
몇몇 윈도우 함수들은 몇가지 서로 다른 성공 이유가 존재한다.
예를 들면, 명명된 이벤트 커널 오브젝트를 생성하는 함수를 호출 할 경우 다음과 같은 두가지 경우 모두 성공을 반환한다.
- 실제로 새로운 커널 오브젝트가 생성되는 경우
- 이미 동일 이름의 커널 오브젝트가 존재하는 경우
이 경우 어떤 이유로 함수가 성공했는지 정확히 구분해야 할 필요가 있다.
이 경우에도, 에러 코드 저장 방식과 같은 메커니즘을 통해 성공 이유를 구분할 수 있게 제공해준다.
따라서, 함수 호출이 성공하더라도, GetLastError를 통해 부가적으로 성공한 이유를 구분해야 할 경우도 생길 수 있다.
Utility Error Lookup
Visual studio는 Error Lookup이라는 작은 유틸리티를 포함하고 있다.
이를 이용하면, 에러코드에 해당하는 메시지 텍스트를 쉽게 확인 할 수 있다.
어플리케이션에서 발생한 에러 메시지를 사용자에게 보여주고 싶을 경우 윈도우에서 제공해주는 FormatMessage 함수를 제공한다.
DWORD WINAPI FormatMessage(
_In_ DWORD dwFlags,
_In_opt_ LPCVOID lpSource,
_In_ DWORD dwMessageId,
_In_ DWORD dwLanguageId,
_Out_ LPTSTR lpBuffer,
_In_ DWORD nSize,
_In_opt_ va_list *Arguments
);
'프로그래밍' 카테고리의 다른 글
CUDA Tutorial 2 (2) | 2018.05.12 |
---|---|
CUDA Tutorial 1 (0) | 2018.04.15 |
X86 Disassembly/Data Structures (0) | 2017.11.26 |
Uninformed Search, Informed Search (0) | 2017.04.21 |
알고리즘 스터디 - 1주차 (0) | 2017.03.17 |