윈도우 함수를 호출하면 호출된 함수는 먼저 전달된 인자의 유효성을 확인하고 함수의 기능을 수행하려 한다. 만일 전달된 인자가 유효하지 않거나 다른 이유로 인해 해당 기능을 수행할 수 없으면 함수는 실패로 반환한다.
윈도우 함수의 대표적인 반환 자료형
자료형 |
실패했을 때의 값
|
VOID |
이 함수는 절대 실패하지 않는다. 아주 적은 수의 윈도우 함수만이 VOID형의 반환 자료형을 가진다.
|
BOOL |
함수가 실패하면 0을 반환한다. 성공 시에는 0이 아닌 값을 반환한다. 반환 값을 TRUE와 비교해서는 안된다. 함수의 성공 여부를 확인하기 위해 FALSE인지 아닌지를 비교하는 것이 가장 좋은 방법이다.
|
HANDLE |
함수가 실패하면 반환 값은 대개 NULL이다. 성공 시에는 유효한 오브젝트 핸들을 반환한다. 몇몇 함수들은 -1로 정의된 INVALID_HANDLE_VALUE를 반환하는 경우가 있기 때문에 주의가 필요하다.
|
PVOID |
함수가 실패하면 NULL을 반환한다. 성공 시에는 PVOID 데이터를 저장하고 있는 메모리 주소를 가리킨다.
|
LONG/DWORD |
상당히 까다로운 형태다. 이러한 종류의 함수는 대개 LONG이나 DWORD형으로 개수를 반환한다. 어떤 이유로 인해 개수를 반환하지 못하게 되면 0이나 -1을 반환한다.
|
윈도우 함수가 실패하면 왜 함수가 실패했는지의 여부를 알아내는 과정이 반드시 필요하다. 마이크로소프트는 발생할 가능성이 있는 모든 에러코드를 32비트 숫자로 정의해 두었다.
윈도우 함수가 실패하게 되면 내부적으로 함수를 호출한 스레드의 스레드 지역 저장소(thread-local storage)에 적절한 에러 코드를 저장해 둔다. 이러한 메커니즘을 통해 여러 개의 스레드가 동시에 수행될 경우라도 상호간에 영향을 미치지 않고 각 스레드별로 에러 코드를 유지할 수 있게 된다. 호출한 함수가 실패한 것으로 판단되면 어떤 에러가 발생했는지 확인하기 위해 GetLastError 함수를 사용할 수 있다.
이 함수는 단순히 가장 최근에 호출된 함수의 에러 코드를 스레드 지역 저장소로부터 가져온다. 이러한 32비트 에러 코드를 좀 더 유용한 정보로 변환할 필요가 있다. WinError.h 헤더 파일은 마이크로소프트가 정의한 모든 에러 코드의 리스트를 가지고 있다.
각각의 에러는 메시지 ID(GetLastError 함수의 반환 값과 비교할 수 있도록 정의된 매크로), 메시지 텍스트(영어로 된 설명), 에러 코드(메시지 ID 대신 이 값을 직접 사용해서는 안된다)의 3가지 요소로 구성되어 있다.
만일 GetLastError 함수를 호출하기 전에 다른 함수를 호출하게 되면 다른 함수의 수행 결과가 겹쳐 써지게 된다. 함수 호출이 성공하면 ERROR_SUCCESS를 에러 코드로 기록한다.
몇몇 윈도우 함수들은 몇 가지 서로 다른 성공 이유가 존재한다. 예를 들어 명명된 이벤트 커널 오브젝트를 생성하는 함수를 호출하면 실제로 새로운 커널 오브젝트가 생성되는 경우 외에도 이미 동일 이름의 커널 오브젝트가 존재하는 경우에도 성공을 반환하게 된다. 이 경우 애플리케이션은 어떠한 이유로 함수가 성공했는지 정확히 구분해야 할 필요가 있다. 따라서 함수 호출이 성공했다하더라도 부가적인 성공의 이유를 확인하기 위해 GetLastError를 호출해야 할 수도 있다.
Watch창을 통해 현재 수행 중인 스레드의 마지막 에러 코드와 메시지 텍스트를 확인 할 수 있다.($err,hr)
에러 코드를 메시지 텍스트로 변환해 주는 FormatMessage 함수도 제공하고 있다.
- 자신만의 에러 코드를 정의하는 방법
개발하는 함수는 하나 혹은 여러 가지 이유에 의해 실패할 수 있을 것이며, 실패의 원인을 호출자에게 반환하도록 작성되어야 할 것이다.
함수가 실패했음을 나타내기 위해서는 실패의 이유를 스레드의 마지막 에러 코드를 설정하고 FALSE, INVALID_HANDLE_VALUE, NULL과 같은 값이나 적절한 값을 반환하도록 함수를 작성하면 된다.
스레드의 마지막 에러 코드를 설정하기 위해서는 SetLastError 함수를 호출하면 된다.
이 함수의 인자로 전달되는 값은 어떠한 32비트 값이라도 상관없다. 만약 WinError.h에 정의된 에러의 원인이 정확하게 에러의 원인을 나타내지 못한다면 자신만의 에러 코드를 작성할 수 있다.
에러 코드 필드
비트 |
31-30 |
29 |
28 |
27-16 |
15-0 |
내용 |
심각도 |
마이크로소프트/고객
|
예약됨 |
식별 코드
|
예외 코드
|
의미 |
0 = 성공
1 = 정보
2 = 주의
3 = 에러
|
0 = 마이크로소프트가 정의한 코드
1 = 고객이 정의한 코드
|
항상 0
|
256까지는 마이크로소프트에 의해 예약됨
|
마이크로소프트나 고객이 정의한 코드
|
- ErrorShow 예제 애플리케이션
FormatMessage가 어떻게 사용되었는지를 확인할 수 있다.
반응형
'책정리 > Windows VIA C,C++' 카테고리의 다른 글
3장 커널 오브젝트 (0) | 2021.07.01 |
---|---|
목차 (0) | 2019.02.23 |