최근에 포맷 스트링과 관련된 문제를 한 번 더 겪어서 여기다 기록을 남겨본다. 문제는 다음과 같은 부분에서 출발했다. 크래시가 났는데 log_writer의 Write 함수를 호출하는 부분에서 났다. 그간 문제없이 잘 사용했던 함수라 증말 증상이 이해가 되질 않았다. 뭔가 buffer 값이 잘못됐는지만 계속 추적했는데 buffer 같은 이상이 없었다.
char buffer[80];
// 버퍼 계산하는 부분
log_writer->Write(L"buffer = '%hs'", buffer);
그렇게 한참을 시도를 하다 놀라운 사실을 발견했다.
클래스가 다음과 같이 선언돼 있었던 것이다. 문제를 눈치 챘는가?
class LogWriter : public ILogWriter
{
public:
virtual void XCALL Write(xcwstr fmt, ...);
virtual void XCALL Write(xcstr fmt, ...);
virtual void XCALL Write(xcwstr fmt, va_arg ap);
virtual void XCALL Write(xcstr fmt, va_arg ap);
};
맞다. 인자가 두개인 함수가 같이 선언된 것이 문제였다. 내가 원했던 링크 경로는 Write(xcwstr fmt, …)이었는데, Write(xcwstr fmt, va_arg ap)로 연결이 됐던 것이다. 흙~ 그래서 클래스를 다음과 같이 바꿨다.
class LogWriter : public ILogWriter
{
public:
virtual void XCALL Write(xcwstr fmt, ...);
virtual void XCALL Write(xcstr fmt, ...);
virtual void XCALL WriteV(xcwstr fmt, va_arg ap);
virtual void XCALL WriteV(xcstr fmt, va_arg ap);
};
가변 인자 함수를 정의할 때에는 각별히 주의해야겠다.