웬디의 기묘한 이야기

글 작성자: WENDYS
반응형

GetLastError() code to Message


Windows 프로그램 개발시 API를 사용하다보면 에러가 났을때 문제를 확인하기 위하여 GetLastError() 를 사용합니다.

하지만 해당 API는 DWORD 로 넘어오기때문에 자주 사용해서 기억하는 코드가 아니면

위 사이트를 이용하여 Error Number와 Message를 비교해야 합니다.


이 때, 디버그 로그를 기록하거나 메시지를 바로바로 보고싶은 경우 이러 번거로움을 해소하기 위하여 FormatMessage API를 사용합니다.


Windows 는 Error Number를 문자열로 변경하기 위해 테이블로 만들어 DLL로 관리하게 되는데 이 DLL이 Message DLL 입니다.


원형은 다음과 같습니다.


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
);

사용법은 다음과 같습니다.


DWORD example_error = 0x5;
TCHAR* message = nullptr;

FormatMessage(FORMAT_MESSAGE_FROM_SYSTEM | FORMAT_MESSAGE_ALLOCATE_BUFFER,
                            nullptr,
                            example_error,
                            MAKELANGID(LANG_NEUTRAL, SUBLANG_DEFAULT),
                            (TCHAR *)&message,
                            0,
                            nullptr);

// ...

LocalFree(message);


이렇게 하면 GetLastError() Code가 0x5 이면 "액세스가 거부되었습니다.\r\n" 라는 결과값이 나오게 됩니다.


여기서 주의해야 할 부분은


1. FORMAT_MESSAGE_ALLOCATE_BUFFER

message의 메모리를 시스템에서 할당을 해달라고 요청하는 부분이며, 이미 할당된 메모리를 사용하는경우엔 해당 플래그를 제거해야합니다.


2. MAKELANGID(LANG_NEUTRAL, SUBLANG_DEFAULT)

메시지의 언어를 지정해주는 부분입니다. 위와같이 지정 한 경우엔 사용자가 제어판에서 설정한 기본 언어로 지정됩니다.


3. LocalFree

FORMAT_MESSAGE_ALLOCATE_BUFFER를 플래그로 지정한경우엔 사용자가 직접 메모리를 해제해주어야 메모리 릭이 발생하지 않습니다.


정도가 되겠습니다.


이제 GetLastError() 만 해서 코드 찾아다니지 말고 메시지로 변경해서 쉽게 볼 수 있겠네요


반응형