MSVC 의 _vsnprintf 버그와 수정 방법
글쓴이: 체스맨 / 작성시간: 수, 2004/02/18 - 6:03오후
MSVC 6.0(서비스팩5 - 확실히 설치했었는지는 기억이 안나네요.)에서
_vsnprintf 함수가 vsnprintf 표준과 호환성을 유지하는데 일부 문제가
있는 것 같습니다.
1. 종료 문자를 감안해서 버퍼 길이를 입력해야 한다. 예를 들어 버퍼 길이가
len 이면, len-1 을 입력해줘야 한다.
2. 문자열이 종료 되지 않아도 음수값(실패)을 리턴하지 않는다. 예를 들어
입력된 버퍼길이가 len 일 때, 문자를 len 만큼 쓰고 len+1 에 문자열을
종료시켜야 하는데, 일단 len 만큼만 써지면 len 이 리턴된다.
다음과 같이 수정할 수 있습니다. 1은 간단히 해결되구요.
...
조금 더 생각을 해 봤습니다. 맨 아래 처음 올린 코드를 올려놨는데,
굳이 memset 할 필요 없이, 무조건 리턴값에 따라 문자열을 종료시키면
되는군요. vsnprintf 표준은 버퍼가 모자르면, 쓰는데까지 쓰고,
리턴값은 모두 성공적으로 쓸 수 있는데 필요한 버퍼 길이를 리턴하도록
돼 있는데, 지금으로서는 리턴값까지 동일하게 맞춰주긴 어려울 것 같네요.
#include <stdio.h> #include <stdarg.h> #include <memory.h> int vsnprintf( char* buf, int len, const char* fmt, va_list arg ) { int result = _vsnprintf( buf, len-1, fmt, arg ); if( result>=0 ) buf[result] = 0; else buf[len-1]=0; return result; }
int snprintf( char* buf, int len, const char* fmt, ... ) { int result; va_list arg; va_start(arg,fmt); result = vsnprintf( buf, len, fmt, arg ); va_end(arg); return result; }
=================================
다음은 처음 올렸던 memset 을 사용하는 좀 비효율적인 코드입니다.
2는 memset 으로 일단 버퍼를 0이 아닌 값으로 채워준 뒤,
_vsnprintf 를 호출한 후 문자열이 잘 종료됐는지 확인합니다.
#include <stdio.h> #include <stdarg.h> #include <memory.h> int vsnprintf( char* buf, int len, const char* fmt, va_list arg ) { int result; memset( buf, 0xff, len ); result = _vsnprintf( buf, len-1, fmt, arg ); if( result>=0 && buf[result] ) buf[result] = 0; return result; }
Forums:
Re: MSVC 의 _vsnprintf 버그와 수정 방법
여전히 리턴값을 vsnprintf 표준과 맞추진 못하지만, 다음과 같이 해서
버퍼 부족을 판단하는 코드가 동일해지도록 할 수 있습니다.
다음과 같이 버퍼 부족을 판단하며 이것은 표준함수를 호출할 때와 동일하게
작성됩니다.
Orion Project : http://orionids.org
Re: MSVC 의 _vsnprintf 버그와 수정 방법
다음은 MSVC 의 _vsnprintf 가 문제가 있는지 알아보는 예제입니다.
문자열 길이가 5인 "Hello" 를 버퍼(길이 5)에 쓰면 오류를 내거나,
"Hell" 까지만 써져야 하는데, "Hello" 까지 쓰고, null terminate
되지 않아서 출력이 다음과 같이 나오면, 문제가 있는 것입니다.
Orion Project : http://orionids.org
댓글 달기