본문 바로가기

카테고리 없음

에러 처리 관련 함수

1
2
3
4
5
6
7
8
9
10
11
#include <stdio.h>
#include <string.h>
#include <errno.h>
 
int main()
{
    printf("errno: %d\n", errno);
    printf("malloc: %s\n", strerror(errno));
 
    return 0;
}
cs

errno.h 에 errno 상수 값이 들어 있다

strerror에 인자로 오류번호를 넣으면 오류 문자열을 가리키는 포인터를 리턴해준다


strerror 예제로 

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
#include <stdio.h>
#include <string.h>
#include <errno.h>
 
int main()
{
    FILE* pFile;
    pFile = fopen("gdfg.txt","r");
    if (pFile == NULL)
    {
        printf("ERROR : %s\n", strerror(errno));
    }
 
//출력 결과 ERROR : No such file or directory
    return 0;
}
cs

파일을 읽을려고 하는데 gdfg.txt라는 파일이 없다. 운영체제는 errno에 에러 번호를 저장한다.(여기서 if구문을 없애면 에러번호를 기록만 하고 출력은 안한다.) errno.h 에 확인 결과 errno 에 전달 된 상수 값은 2이다( strerror(2) 해도 줄력 가능 ) 

strerror에 2 라는 값이 전달되면서 문자열 No such file or directory 이 출력 된다


윈도우 환경에서는 위 함수들을 지원한다고 한다. 하지만 이는 시스템과 관련된 메시지들만 지원하고 소켓 메시지는 별도의 함수를 사용하여야 한다고 한다


윈도우 환경에서의 소켓 관련 에러 메시지는 FormatMessage와 WSAGetLastError함수를 이용한다

WSAGetLastError 함수는 위의 errno 변수와 유사하다 WSAGetLastError 함수를 호출하면 최근에 발생한 소켓 함수에서 발생한 에러번호를 리턴을 하는데

이 값이 정수형 값이라 어떤 의미를 가지고 있는지를 모른다

이에 따라 정수값을 이해하게 문자열 형태로 바꿔주는 함수가 FormatMessage 함수이다 위의 strerror 함수와 유사한 것을 알 수 있다

DWORD WINAPI FormatMessage(
_In_ DWORD dwFlags, // 호출방법 동적할당or운영체제
_In_opt_ LPCVOID lpSource, // NULL
_In_ DWORD dwMessageId, // 에러번호
_In_ DWORD dwLanguageId, // 언어
_Out_ LPTSTR lpBuffer, //오류메시지의 시작주소
_In_ DWORD nSize, // 0
_In_opt_ va_list *Arguments //NULL
);


FormatMessage 함수를 동적으로 할당했으면 동적할당공간을 해제하는 함수는 LocalFree() 함수를 이용한다


다음을 보기 전에 생소한 거 하나를 먼저 쓰겠다
바로 LPVOID 라는 자료형이다
맨처음 이것을 보았을 때 LP는 포인터라는 것을 알겠고.. VOID는 ID? 뭐지 이런 생각을 했다.
익숙한 void가 대문자로 바뀌니 이렇게 못 알아차리다니...
즉 LPVOID== void * 라는 것인데 살짝 보니까 typedef void far 라는게 나온다 far?? 이것은 예전 16비트와의 호환성을 위한 거라고만 생각해두자
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
 
//추가적으로 ws2_32.lib를 라이브러리 추가해줘야 한다
int main()
{
    LPVOID IpMsgBuf;
    
    FormatMessage(
        FORMAT_MESSAGE_ALLOCATE_BUFFER |
        FORMAT_MESSAGE_FROM_SYSTEM,
        NULL, WSAGetLastError(),
        MAKELANGID(LANG_NEUTRAL, SUBLANG_DEFAULT),
        (LPTSTR)&IpMsgBuf, 0NULL);
 
    printf("WSAGetLastError: %d\n", WSAGetLastError());
    printf("IpMsgBuf: %s\n", IpMsgBuf);
 
    LocalFree(IpMsgBuf);
 
    return 0;
}
cs


종합 소스
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
#include <stdio.h>
 
#ifndef __linux__
#include <WinSock2.h>
#include <Windows.h>
#define perror(msg) winperror(msg)
 
void winperror(char* msg);
#endif // !__linux__
 
int main()
{
    perror("hello");
    return 0;
}
 
#ifndef __linux__
void winperror(char* msg)
{
    LPVOID IpMsgBuf;
 
    FormatMessage(
        FORMAT_MESSAGE_ALLOCATE_BUFFER |
        FORMAT_MESSAGE_FROM_SYSTEM,
        NULL, WSAGetLastError(),
        MAKELANGID(LANG_NEUTRAL, SUBLANG_DEFAULT),
        (LPTSTR)&IpMsgBuf, 0NULL);
    
    printf("%s : %s\n", msg, IpMsgBuf);
    LocalFree(IpMsgBuf);
    
}
#endif // !__linux__
 
cs
설명
1) 윈도우 환경 실행시 :
#ifndef __linux__
~
#endif 문장이 전처리기에 의해 소스가 치환되어서 실행
2) 리눅스 환경일 시 그대로~