에러 핸들링은 말 그대로 윈도우 프로그램이 내부 함수들을 진행하면서 발생시킬 수 있는 에러들을 제어하는 것을 말합니다.

윈도우 프로그램 뿐만 아니라 기본적으로 모든 애플리케이션에서는 에러를 잘 처리해줘야 예기치 못한 기능 실패시에 프로그램이 Crash 되는 것을 막아줄 수 있습니다. (기능은 처리되지 못할 지라도 프로그램은 계속 동작할 수 있도록)


아래는 윈도우 함수들이 사용하고 있는 리턴형들입니다.


자료형 

실패 

 VOID

 실패하지 않음, 리턴형 없음 

 - 필요 외 프로그래밍시에 VOID형 함수 설계는 피하는것이 좋습니다.

 BOOL

 실패시 0 리턴, 성공시 0이 아닌 값

 - 때문에 TRUE(1)를 비교하면 성공했더라도 제대로 된 결과를 얻지 못할 수 있습니다.

 - 함수 내에서 명시적으로 TRUE를 리턴하는 경우가 아니라면 리턴 값을 FALSE와 비교해야    합니다.

 HANDLE

 실패시 NULL 리턴, 성공시 핸들리턴

 - 일부 함수들은 01인 INVALID_HANDLE_VALUE를 리턴하는 경우도 있음

 - msdn을 참고하면 실패시 INVALID_HANDLE_VALUE인지 NULL인지 알 수 있음

 - 만약 실패 값을 함수 동작 이후 외부에서 잘못 비교하게 되면 실패했음에도 성공으로 

   판단할 수 있기 때문에 리턴형 확인은 꼭 필요합니다.

 PVOID

 실패시 NULL, 성공시 PVOID가 데이터를 저장하고 있는 메모리의 주소를 가리킵니다.

 - 포인터

 LONG/DWORD

 실패시 0이외의 값 (1이나 -1 등). 나머지는 1 이상으로 define 된 에러코드들을 리턴

 - 대체로 성공시 1을 리턴 : ERROR_SUCCESS or STATUS_SUCCESS


이와 같이 성공과 실패를 가르는 이유는 함수가 실패했을 때 왜 실패했는지 알아야 하기 때문입니다.


윈도우 함수가 실패했을 때에는 함수를 호출한 스레드의 스레드 로컬 스토리지에 발생한 에러코드를 저장합니다.

호출한 함수가 실패하는 지점에 GetLastError() 함수를 사용한다면 가장 마지막에 발생한 에러를 확인할 수 있습니다.

- 실패 지점에서 바로 호출해야합니다. 나중에 호출하면 다른 값을 리턴할 가능성이 생깁니다.


에러코드의 자세한 내용을 보려면 플랫폼 SDK의 WinError.h를 참고하시면 됩니다.

윈도우에서 정의한 모든 상황에 대한 에러 코드를 확인할 수 있습니다.


윈도우 에러코드

https://msdn.microsoft.com/en-us/library/windows/desktop/ms681382(v=vs.85).aspx

(너무 양이 많아서 에러코드를 따로 기재하지는 않고 링크로 대체하겠습니다.)


간혹 윈도우 함수들 중에서는 여러가지 성공의 경우가 있습니다.

CreateEvent 함수를 예로 들면, 여러가지 성공의 이유가 존재합니다.

- Event 오브젝트 생성 -> 성공

- 이미 같은 이름의 Event 오브젝트가 존재해 새로 생성하지 않아도 되는 경우 -> 성공

이런 경우 처럼 다른 성공의 이유를 확인해야 할 때에도 GetLastError() 함수를 호출할 수도 있습니다.

CreateEvent 함수의 msdn을 보면 이미 생성 된 경우에는 ERROR_ALREADY_EXISTS를 리턴한다고 되어있습니다.

때문에, 함수 설계시 다른 성공의 이유도 확인하지 않으면 함수가 성공했음에도 실패로 처리될 수 있습니다.


에러코드 역시 필요한 경우 윈도우에서 제공하는 에러코드 이외 따로 Define하여 정의해 자체적으로 에러 핸들링을 할 수도 있습니다.

하지만, 가급적이면 윈도우에서 정해준 에러코드를 사용하는 것이 좋습니다.


함수를 진행시키다 에러코드를 설정하고 싶을 때에는 SetLastError(DWORD dwErrCode) 함수를 이용하면 됩니다.

예를 들면 함수 실패 지점에서 유효하지 않은 인자를 받은 경우 함수 실패를 나타내기 위해 윈도우 에러코드인 ERROR_INVALID_PARAMETER를 활용할 수 있습니다.


DWORD ErrorCode(HANDLE hwnd)

{

DWORD dwRtVal = ERROR_SUCCESS;

      if ( NULL == hwnd )

{

SetLastError(ERROR_INVALID_PARAMETER);

return GetLastError();

}

........

}

함수의 유효성을 검증하기 위해 위와 같은 형태로 윈도우 에러코드를 활용할 수 있습니다.

(저의 경우는 return ERROR_INVALID_PARAMETER로 바로 리턴하기도 합니다.)


윈도우 프로그래밍을 하면서

- 함수의 기능 실패 이유를 알기 위해

- 기능이 실패되더라도 프로그램의 동작은 계속 되도록

하기 위해 에러 핸들링은 필수적으로 필요하고 반드시 잘 처리되어야 합니다.

Posted by 긍정왕오킹