NULL 문자!? 0x00
최근에 계속 프로젝트를 하다가 상사분의 조언을 들었다. 프로젝트의 특정 부분에 관한 말씀이셨는데, 파일을 Read하는 부분이었다. MFC에서 CFile을 이용해서 읽던 중 항상 읽어드리는 데이터를 저장하는 버퍼를 크기보다 'nLen+1' 하나 더 크게 항상 생성하였다. 이 부분에 의문의 두시고 질문은 하신 것이다. 나는 당연히 항상 기존문자열의 길이+1을 하여 저장을 하였기에 생각을 못했지만 실무자의 눈에는 썩 좋은 코드로 생각이 되지 않으셨던 것이다. 물론 유동적으로 사용하는 버퍼이면 NULL은 넣는것은 당연하지만 한번 읽는데 사용하는 버퍼의 경우에는 굳이 한바이트 더 넣어줄 이유는 없다는 것이다.
나의 경우에는 직접 경험하고 봐야지 기억을 하는 타입이라서 곧바로 나름 실험에 들어갔다.
※ 추가 180602
내 코드만으로 볼 경우에는 충분히 오해할 수 있는 상황이다. 상사분 질문의 의도는 왜 이미 초기화가 된 공간에 [+1] 을 수행시켜 코드를 복잡하게 만드는건가??
# 문제의 코드
1 2 3 4 5 6 7 8 9 | nLen = CFile::GetLength() // 임시로 경우를 설명하기 위한 것임.. ... 생략 ... wchar_t *pszUnicode; char *pszMulti; pszUnicode = new wchar_t[sizeof(wchar_t)*(nLen+1)]; pszMulti = new char[sizeof(char)*(nLen+1)]; memset(pszUnicode,0,sizeof(wchar_t)*(nLen+1)); memset(pszMulti,0,sizeof(char)*(nLen+1)); | cs |
# case 1
1 2 3 4 | char *pszBuffer = "HELLO WORLD"; char szBuffer[MAX_PATH] = {0,}; strcpy(szBuffer, pszBuffer); | cs |
1 2 3 4 5 6 7 8 9 | char *pszBuffer = "HELLO WORLD"; char *szBuffer = NULL; int nLen = strlen(pszBuffer); szBuffer = new char[nLen+1]; strcpy(szBuffer, pszBuffer); delete [] szBuffer; | cs |
1 2 3 4 5 6 7 | char *pszBuffer = "HELLO WORLD"; char *szBuffer = NULL; szBuffer = new char[MAX_LEN+1]; strcpy(szBuffer, pszBuffer); delete [] szBuffer; | cs |
1 2 3 4 5 6 7 8 9 10 | TCHAR *pszPath = _T(".\test.txt"); HANDLE h = CreateFile(pszPath, GENERIC_READ , FILE_SHARE_READ, 0, OPEN_EXISTING, 0, 0); if( h != INVALID_HANDLE_VALUE) { char szBuffer[5+1] = {0,}; DWORD dwLen = 0; ReadFile(h, szBuffer, 5, &dwLen, 0); CloseHandle(h); } | cs |
char szBuffer[5] = {0,};
▶ 파일 입력 메모리 관련 실험
환경 : Visual Studio 2008 을 이용하였고, 2013에서도 동일하다.
함수,클래스 : CFile, CreateFile, UTF-8 종류의 파일을 읽어들였다. 매 부분마다 메모리를 확인하였다. 주의하여서 볼 것은 각 파일의 내용이 다르기 때문에 파일 크기는 유동적이라는 점과
환경은 Alt+F7 단축키로 설정에 들어가서 변경가능하다.
[ 유니코드 환경 ]
|
FileSize ( 파일크기 ) |
해독 유/무 |
NULL 유/무 |
UNICODE |
384 |
모든문자 해독 가능 |
무 |
ANSI |
220 |
모든문자 해독 불가능 |
무 |
UTF-8 |
252 |
모든문자 해독 불가능 |
무 |
[ 멀티바이트 환경 ]
| FileSize ( 파일크기 ) | 해독 유/무 | NULL 유/무 |
UNICODE | 384 | 모든문자 해독 불가능 | 무 |
ANSI | 220 | 모든문자 해독 불가능 | 무 |
UTF-8 | 252 | 한글제외하고 읽어짐 | 무 |
▶ 결과
문자열을 읽어올때 버퍼 속에는 NULL이 들어와있지 않았다. 왜 그런것인지 의문이 생긴다. 분명히 텍스트를 읽어오기 위해서는 NULL을 통하여 문자열의 끝을 확인한 데이터를 Read하였을 것이다. 그런데 읽어올때는 NULL만 제외하고 읽어온다...?? 뭔가 내가 모르는 어떤 부분이 있는것이가. 우선은 눈으로 확인한 결과가 나에게는 팩트이기 때문에, 어떤것이 확실한 답인지는 추후에 기록해 둘것이다.
※ 추가 180602
+ ReadFile
이번 경우로 확실한 것은 ReadFile은 NULL을 포함하여 읽지 않는다는 점이다.
그렇기 때문에 ReadFile을 할 경우에는
1. 데이터 보다 크게 공간을 확보하기.
2. 초기화 하기 ( 쓰레기값때문에 초기화 해주어야한다. 그렇지 않으면 문자열을 끝을 찾지못한다. )
+ strlen, strcpy 관련
strlen 은 문자열의 길이만 리턴하고( NULL 제외), strcpy는 문자열의 NULL까지 포함하여서 복사한다. 즉 이 두개를 같이 사용하기 위해서는 strlen+1 의 추가공간을 할당하고 0으로 반드시 초기화를 해주어야한다. 즉 동적인 크기를 사용하기 위해서는 초기화라는 개념과 문자열의 길이에 대한 개념이 잘 잡혀있어야 원하는 데이터를 얻는데 문제가 발생하지 않는다.
▶ 질문거리
1. 그렇다면 전체를 읽는 것이 아니라 부분을 읽어들인다면 NULL은 넣어줘야하지 않는가? ( 나의 개념으로는 당연한 생각 이다. )
답 : 당연하다. NULL을 넣어주지 않으면 컴퓨터는 멍청해서 NULL을 찾을때까지 읽을 것이다.
'훈, IT 공부 > C,C++,MFC' 카테고리의 다른 글
[MFC]트레이아이콘(Tray)과 풍선(Balloon) 알림 사용 (2) | 2018.08.12 |
---|---|
[궁금점]winApi WriteFile 함수의 동작 (0) | 2018.06.02 |
[MFC] WM_MOUSEHOVER, WM_MOUSELEAVE 메시지 이용방법 (0) | 2018.05.07 |
[MFC]MFC 버튼을 이용한 프로젝트 #1 버튼 추가 + 사이즈조절 (2) | 2018.05.07 |
[MFC] Dialog 크기조절 관련 함수,메시지 (0) | 2018.05.01 |
댓글