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 표준과 맞추진 못하지만, 다음과 같이 해서
버퍼 부족을 판단하는 코드가 동일해지도록 할 수 있습니다.
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; return result; } buf[len-1]=0; return len; }다음과 같이 버퍼 부족을 판단하며 이것은 표준함수를 호출할 때와 동일하게
작성됩니다.
result = snprintf( buf, len, "%s\n", "Hello, world." ); if( result>=len ) { /* 버퍼 부족 */ }Orion Project : http://orionids.org
Re: MSVC 의 _vsnprintf 버그와 수정 방법
다음은 MSVC 의 _vsnprintf 가 문제가 있는지 알아보는 예제입니다.
#include <stdio.h> int main( void ) { static char buf[] = "Hello, world\n"; int result = _snprintf( buf, 5, "Hello" ); if( result>0 ) printf( "return value=%d\n", result ); printf( buf ); return 0; }문자열 길이가 5인 "Hello" 를 버퍼(길이 5)에 쓰면 오류를 내거나,
"Hell" 까지만 써져야 하는데, "Hello" 까지 쓰고, null terminate
되지 않아서 출력이 다음과 같이 나오면, 문제가 있는 것입니다.
Orion Project : http://orionids.org
댓글 달기