정리

[Win32 API] 가변인자 처리 방식, 그리고 오류

저장소/VC++
최근 가변인자 처리 과정에서 생각치 못했던 오류가 발생했다.(원인은 내 실수 ㅡㅜ)
그리 어려웠던 것도 아니었는데 시간은 시간대로 소비하고 간신히 원인을 찾았는데 정말 생각하지도 못했던 문제였기에 적어본다.

우선 가변인자 처리에는 _vstprintf_s의 사용보다는 Strsafe.h에 있는 StringCchVPrintf 함수를 주로 사용한다.
익숙해져서이기도 하지만 안전한 문자열 처리를 위해 Strsafe.h에 있는 함수들을 사용하기 때문이다.
내가 보편적으로 쓰는 처리방식은 아래와 같다.
void OuputFunction(LPCTSTR lpszFormat, ...)
{
	TCHAR szContent[1024] = {0,};

	va_list vlist;
	va_start(vlist, lpszFormat);
	StringCchVPrintf(szContent, 1024, lpszFormat, vlist);
	va_end(vlist);

	...
}
로그 기록 처리에 주로 위와 같이 구현해서 사용하는데 쓰다보니 가변인자 처리를 2번에 걸쳐서 쓰게되는 상황이 생겼는데
문제는 여기서 발생했다.
처리 상황을 똑같이 구현해놓기는 뭐하고 다음과 같이 처리해놓으니 문제 증상이 재현된다.
void OuputFunction(LPTSTR _lpszRet, size_t _cchLen, LPCTSTR _lpszFormat, ...)
{
	TCHAR szContent[1024] = {0,};

	if(NULL != _lpszFormat)
	{
		va_list vl;
		va_start(vl, _lpszFormat);
		StringCchVPrintf(szContent, sizeof(szContent) / sizeof(TCHAR), _lpszFormat, vl);
		va_end(vl);
	}

	if(NULL != _lpszRet)
		StringCchCopy(_lpszRet, _cchLen, szContent);
}

void SomeFunction()
{
	TCHAR* pszSampleString = _T("C:\\Users\\Administrator\\Desktop\\style-12px%20Helvetica%2C%20Arial%2C%20Sans-serif;606060_FFFFFF_3399CC_99FF33_006600_666666_FFFFFF;0px%20solid;_blank[1].htm");
	TCHAR szContent[1024] = {0,};

	OuputFunction(szContent, _countof(szContent), _T("[test] %s"), pszSampleString);
	OuputFunction(NULL, 0, szContent);

	_tprintf_s(_T("%s\n"), szContent);
}
증상 재현을 위해 대충 만들었기 때문에 그냥 이러한 상황이 있다 가정한다.
주목해야 할 부분은 바로 pszSampleString의 파일 경로다.
첫 번째, OuputFunction을 거치고나면 szContent에 "[test] C:\Users..." 요로코롬 값이 들어간다.
두 번째, szContent가 다시 OutputFunction의 Format으로 전달되는데 이 때 문자열에 포함된 %로 인하여 문제 발생.
(디버깅으로 하나하나 찾아보니 %s를 두 번째 처리할 때 Access Violation이 발생했다.)

보통 가변인자 처리를 많이 하는 것도 아니고 2번에 걸쳐 처리되게 만들지도 않는다.
좀 편하게 만들자고 여기저기 만들어뒀는데 그것땜에 이런 문제를 발견했다.
생각치도 못했던 파일명으로 인하여 예상하지 못했던 증상을 발견했네. ㅡㅜ
이번 가변인자 처리과정의 문제로 인해 좀 더 생각하고 만들어야겠단 반성을 하게됐다.
끝!