1. 01. 에러 핸들링
제프리 리처의 Windows VIA C/C++
2022.01.04 함송연
1. 자신만의 에러 코드를 정의하는 방법
2. ErrorShow 예제 애플리케이션
1
2. 윈도우 함수의 반환 타입
자료형 실패했을 때의 값
VOID 이 함수는 절대 실패 하지 않는다.
BOOL 성공시 0이 아닌 값, 실패하면 0
(주의 : 성공시 0이 아닌 값이기에 TRUE(1)과 비교하지 말자)
HANDLE 성공시 유효한 핸들,
실패하면 0(NULL) or (INVALID_HANDLE_VALUE)
실패의 경우가 나뉘므로 SDK를 참조하여 프로그래밍을 하자.
PVOID 성공시 데이터를 저장하고 있는 메모리 주소를 반환,
실패시 NULL반환
LONG/DWORD HANDLE과 마찬가지로 실패의 경우가 각 함수마다 다르므로 SDK를 참조하여 프로그래밍을 하자.
2
3. 에러 코드
DWORD GetLastError()
호출 함수가 실패하면 함수를 호출한 스레드의 스레드 지역 저장소에 적절한 에러 코드를 저장해 둔다.
GetLastError()를 통해 에러 코드를 읽어올 수 있다.
3
WinError.h (훨씬 많음)
메시지 내용 #define 값
Messageld : ERROR SUCCESS
MessageText :The operation completed successfully.
ERROR_SUCCESS 0L
NO_ERROR 0L
SEC_E_OK ((HRESULT)OxOOOOOOOOL)
Messageld: ERROR INVALID FUNCTION
MessageText: Incorrect function.
ERROR_INVALID_FUNCTION 1L
Messageld: ERROR FILE NOT FOUND
MessageText: The system cannot find the file specified.
ERROR_FILE_NOT_FOUND 2L
MessageId: ERROR PATH NOT FOUND
MessageText: The system cannot find the path specified.
ERROR_PATH_NOT_FOUND 3L
MessageId: ERROR_TOO_MANY_OPEN_FILES
MessageText: The system cannot open the file
ERROR_TOO_MANY_OPEN_FILES 4L
MessageId: ERROR ACCESS DENIED
MessageText: Access is denied.
ERROR_ACCESS_DENIED 5L
4. Visual Studio에서 에러 코드 확인
조사식
4
Error Loockup (도구 > 오류 조회)
조사식 > $err,hr 추가 (hr : 메세지를 함께 표시)
값을 통해 오류 메시지를 조회할 수 있다.
5. 자신만의 에러 코드를 정의하는 방법
VOID SetLastError (DWORD dwErrCode);
5
에러 코드를 남기는 함수. 이때 DWORD로 자신만의 에러 타입을 만들어두고 남기면 된다.
각 필드가 의미하는 바는 24장 “예외 처리기와 소프트웨어 예외”에서 상세히 다룰 예정.
비트 31-30 29 28 27-16 15-0
내용 심각도 마이크로소프트/고객 예약됨 식별 코드 예외 코드
의미 0 = 성공
1= 정보
2= 주의
3= 에러
0 = MS
1 = 고객이 정의한 코드
항상 0 256까지는 MS 예약,
신규로는 257~4096 사용
MS나 고객이 정의한
코드
에러 코드 필드
6. Error Show 예제
개요
6
에러 코드를 입력하면 에러 메시지를 출력하는 다이얼로그 박스 프로그램. (VS의 Error Lookup과 동일한 기능)
다운로드
에러 코드를 입력하면 에러 메시지를 출력하는 다이얼로그 박스 프로그램. (VS의 Error Lookup과 동일한 기능)
한빛미디어 자료실 : https://www.hanbit.co.kr/support/supplement_list.html
(책 이름 검색하여 예제 소스 다운로드)
cggos/windows_via_cpp: Source Code of the Book "Windows Via C/C++" By Jeffrey Richter And Christopher Nasarre (github.com)
깃허브
7. Error Show 예제
39 line. Dlg_OnCommand 함수
7
windows_via_cpp/ErrorShow.cpp at master · cggos/windows_via_cpp (github.com)
FormatMessage
// Get the error code's textual description
BOOL fOk = FormatMessage(
FORMAT_MESSAGE_FROM_SYSTEM | FORMAT_MESSAGE_IGNORE_INSERTS |
FORMAT_MESSAGE_ALLOCATE_BUFFER,
NULL, dwError, systemLocale,
(PTSTR) &hlocal, 0, NULL);
첫번째 매개변수 : 플래그
FORMAT_MESSAGE_FROM_SYSTEM : 운영체제가 정의하고 있는 에러 코드와 대응되는 메시지 텍스트를 얻고 싶음
FORMAT_MESSAGE_ALLOCATE_BUFFER : 에러 메시지 텍스트를 저장할 수 있는 충분한 메모리 공간을 할당해 줄 것을 요청,
할당된 메모리 블록을 가리키는 핸들은 hlocal 변수를 통해 반환
FORMAT_MESSAGE_IGNORE_INSERTS : 메세지 텍스트에 %로 시작하는 자리 표시자를 실질적인 값으로 변경하지 않을 것을 지정.
이 플래그를 인자로 전달하지 않으려면 반드시 자리 표시자에 나타날 정보를 Arguments 매개변수를 통해 전달해야 한다.
(마지막 인자 NULL로 된 부분)
하지만 예제의 경우 메시지 텍스트의 내용이 무엇인지를 미리 알 수 없어 Arguments 매개변수를 활용할 수 없다.
세 번째 매개변수 : 에러 코드
네 번째 매개변수 : 언어 식별자
(0이라면 시스템 기본 언어 설정. 어떤 언어의 운영체제가 설치되어 있는지를 미리 알 수 없다면 이 값을 특정 언어를 지정하도록 하드코딩 해서는 안된다.)
8. Error Show 예제
39 line. Dlg_OnCommand 함수
8
windows_via_cpp/ErrorShow.cpp at master · cggos/windows_via_cpp (github.com)
FormatMessage
// Get the error code's textual description
BOOL fOk = FormatMessage(
FORMAT_MESSAGE_FROM_SYSTEM | FORMAT_MESSAGE_IGNORE_INSERTS |
FORMAT_MESSAGE_ALLOCATE_BUFFER,
NULL, dwError, systemLocale,
(PTSTR) &hlocal, 0, NULL);
FormatMessage가 성공하면 :
메세지를 담은 메모리 블록(hlocal)을 이용하여 스크롤 가능 창에 메세지를 출력
FormatMessage가 실패하면 :
에러 코드가 네트워크 에러와 관련되어 있는지 확인하기 위해 NetMsg.dll로부터 에러 코드를 다시 찾아보기 위해 NetMsg.dll 모듈의 핸들을 이용하여 FormatMessage를 재
호출
(20장 “DLL의 고급 기법”)
이와 같이 각각의 DLL(혹은 .exe)은 자신만의 에러 코드와 메시지 텍스트를 포함할 수 있다.
이러한 정보들은 메시지 컴파일러(MC.exe)를 통해 특정 모듈에 리소스 형태로 추가된다.
이러한 이유로 Visual Studio의 Error Lookup 유틸리티는 모듈 다이얼로그 박스를 이용하여 모듈을 추가하는 방법을 제공하고 있다.