64비트 Win7에서 VCi가 죽은 이유는…

VCi 이전버전, 정확히는 3.8c까지는 64비트 Win7에서 오류가 발생했다.
32비트에선 문제가 없고, 64비트에서만 문제가 발생해서 OS의 문제라고 쉽게 생각했다.
하지만…


1. 문제의 발단

VCi는 VC++ 6.0으로 개발되었는데, VC6에는 atof()의 wchar_t 버전이 없다.
(웃긴 건 atoi()의 wchar_t 버전은 있다는 거)
따라서, wchar_t에서 atof()를 사용하려면 char로 복사를 한 뒤에 atof()를 사용해야 한다.


2. 문제가 발생한 위치

VCi의 소스를 그대로 적은 건 아니지만, 대략 아래와 같은 소스에서 문제가 발생했다.

CString cs=_T("23.976");
int iLen = cs.GetLength();
char *ch = new char[iLen+1];
int i=iLen;
while (i-- >= 0) ch[i] = (char)(cs.GetAt(i));
double d = atof(ch);
delete ch;

오류가 발생한 곳은 6행의 atof().
물론, atof() 자체에 버그가 있는 건 아니고, 인자로 넘어간 *ch가 0으로 정상종료되는 문자열이 아니었던 것이다.

진짜 문제는 5행의 while()에 있었다.
while (i-- >= 0)에서 i를 하나 줄이는 시점은 ch[i]=… 를 실행하기 인데, 이걸 실행 라고 착각한 것이다.
즉, 문자열을 복사할 때 "23.976(0)"이 아닌 "(?)23.976"이 복사된 것이고, 이에 따라 atof()는 오류를 발생시킨 것이다.

32비트 OS들에서 문제가 없던 건 단지 운이 좋았던 것 뿐이다. OTL


3. 해결

거창한 해결이랄 것도 없이, (쓸데없이 복잡하게만 씌여진) 4, 5행을 아래와 같이 상식적으로 수정했다.

CString cs=_T("23.976");
int iLen = cs.GetLength();
char *ch = new char[iLen+1];
for (int i=0; i<=iLen; i++)
  ch[i] = (char)(cs.GetAt(i));
double d = atof(ch);
delete ch;

지금 코드를 들여다보고 느낀 건데, 왜 저렇게 희안한 구조를 썼는지 모르겠다.
상식적으로 for()를 쓰면 되는데…