AfxExtractSubString 함수 사용 시 메모리 부족 오류 나는 현상
if( AfxExtractSubString(szTmpBuffOne, szTmpBuff, i, '\n') )
여기서 szTmpBuff는 사용자에게 입력받은 경로 값
-> 경로 길이가 너무 길어서 함수 내부에서 Exception 발생, 디버그로 돌리면 '메모리가 부족합니다'라는 오류 메시지 출력
따라서 그냥 메모리 힙 잡아서 구분자 사용하려고 수정
char str[] = "My name is Hong Gil Dong";
char *pToken = NULL;
char *pSeparator = " "; // 구분자
/* 첫번째 수행시에" " 구분자로 자른 후 My 라는 문자열을 리턴합니다. 정확히 얘기하면 주소값을 리턴합니다.
나머지 name is.... 문자열은 strtok() 함수 내부에서 static 변수로 기억되고 있다가,
두 번째 호출시 파라미터에 NULL을 받게되면 기억하고 있던 name is... 문자열을 꺼내어 다시 자르게 됩니다. */
pToken = strtok(str, pSeparator);
printf("%s\n", pToken);
/* 두번째 수행부터 strtok() 호출시에는 파라미터에 NULL을 넣음으로 계속해서 자르기 작업을 수행하게 됩니다.
strtok가 NULL을 반환하면 더 이상 자를 문자열이 없으므로 while 문을 빠져 나갑니다. */
while (NULL != (pToken = strtok(NULL, pSeparator)))
{
printf("%s\n", pToken);
}
기본적인 함수 사용 방법은 예제와 같습니다. 하지만 주의사항으로 세 가지가 있습니다. 첫 번째는 strtok() 함수 사용 후 원본 문자열인 str[]의 데이터를 보장할 수 없습니다. 확인 결과 위 예제에서 strtok() 함수를 수행 후에 str[]내부의 “ “ space 문자는 NULL로 모두 변환 되어버립니다.
해결 방법은 원본 데이터를 보존하기 위한 임시 버퍼 변수를 사용하는 방법이 있겠습니다.
두 번째는 VS6.0에서는 strtok()는 잘 작동하지만 VS2005이상에서는 원할한 작동을 보장하지 않습니다. 그러므로 온라인상에서도 주요 포럼 게시물들을 살펴보면 strtok() 보다는 VS2005 이상에서 사용할 수 있게끔 개선된 strtok_s() 함수의 사용을 권장하고 있습니다.
세 번째는 strtok() 함수는 내부적으로 문자열 분리를 위한 위치 식별을 위해 static변수를 놓고 정적 공유하여 사용한다고 합니다. 그러므로 현재 진행 중인 분리 작업을 훼손할 수 있기 때문에 Thread-Safe 하지 않습니다. 이는 하나의 스레드에서 서로 다른 문자열을 동시에 분리하게 되면 문제가 발생될 여지가 있습니다. 이를 개선한 함수가 strtok_s()가 되겠습니다.
strtok_s() 의 사용법은 strtok()과 동일하나 세 번째 인자가 추가 되었습니다.
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 | void CControlTestDlg::OnBnClickedButtonCheckstring() { // TODO: Add your control notification handler code here CString strStringTest; TCHAR * szStringTest = NULL; GetDlgItem(IDC_EDIT_StringTest)->GetWindowText(strStringTest); szStringTest = (TCHAR *) malloc( strStringTest.GetLength() * sizeof(TCHAR) ); //ZeroMemory(szStringTest, strStringTest.GetLength() * sizeof(TCHAR) ); BOOL isValidPath = IsValidPath(szStringTest, strStringTest.GetLength() * sizeof(TCHAR) ); } // ValidCheck BOOL CControlTestDlg::IsValidPath(TCHAR* szInPaths, int szInPathsBuffSize) { TCHAR * pSeparator = _T("\r\n"); TCHAR * context = NULL; TCHAR * pPath = NULL; BOOL ret = TRUE; TCHAR szDebugString[MAX_PATH] = {0}; CString strInPaths; strInPaths.SetString(szInPaths ); MessageBox(strInPaths); pPath = wcstok_s(szInPaths, pSeparator, &context); _stprintf_s(szDebugString, _T("wcstok_s(szInPaths, pSeparator, &context) Return = [0x%x]"), pPath); MessageBox(szDebugString); return ret; } |
사용자한테 EditCtrl로 입력받은 값을 strStringTest 에 저장한 후
strStringTest 값을 szStringTest에 복사를 안하고(깜빡함) 위처럼 테스트했더니 자꾸만 pPath가 NULL 값이 안나옴.
디버깅 하니까 szStringTest에 쓰레기 값이 들어가있었는데, 우연찮게 \r\n이 그 안에..있었나봄 (디버깅으로 확인했을 땐 이상한 특수문자들이 나왔음)
그래서 pPath가 valid한 값으로 나옴
Line 9 에서 ZeroMemory 를 주석 푸니까 pPath가 return NULL 하더라...
'Windows > MFC 강좌 & Tips' 카테고리의 다른 글
(2) MFC 초기화 함수 : InitInstance, OnInitDialog (0) | 2020.08.08 |
---|---|
(1) MFC 시작하기 (1) | 2020.08.08 |
Dialog에서 툴바 생성 (0) | 2017.08.23 |
UpdateData 함수 (0) | 2017.01.04 |
Dialog based 그림판 (2) | 2017.01.04 |