Question

I was writing a utility function to do sprintf like formatting for std::string or std::wstring based on Unicode settings.

#ifdef _UNICODE
typedef std::wstring MyString ;
typedef TCHAR MyChar ;
#define MYTEXT TEXT
#else
typedef std::string MyString ;
typedef char MyChar ;
#define MYTEXT
#endif //_UNICODE

MyString Utils::GetStringPrintf(const MyString kstrText, ...)
{
    int iCharsWritten = 0 ;
    MyString strFinal ;
    MyChar szBufferTouse[8194] ; //Hopefully Long enough
    va_list     fmtList ;
    va_start(fmtList, kstrText) ;
    /*int iVal = va_arg(fmtList, int) ;*/ =>Just for debugging

#ifdef _UNICODE
    iCharsWritten = _stprintf_s(szBufferTouse,  8194, kstrText.c_str(), fmtList) ;
#else
    iCharsWritten = sprintf_s(szBufferTouse, 8194, kstrText.c_str(), fmtList) ;
#endif //_UNICODE

    va_end(fmtList) ;
    strFinal = szBufferTouse ;
    return strFinal ;
}

When called like :

int iId = 2 ;
MyString strFileName = Utils::GetStringPrintf(MYTEXT("Student_%d.png"), iId) ;  

//For Unicode am getting Student_1633600.png instead of Student_2.png //For non-Unicode am getting Student_1633800.png instead of Student_2.png

Upon debugging I do get the value of iVal as 2, but somehow the values get bad upon passing to sprintf.

However if I call, sprintf directly,

MyChar szFilename[200] ;
int iId = 2 ;
_stprintf_s(szFilename, 200, MYTEXT("Student_%d.png"), iId) ;

Am getting proper output, i.e Student_2.png

I did refer other posts in Stack Overflow regarding sprintf functionality and found my code to be doing quite similar to those. Is there any problem in passing va_list repeatedly to functions.

Was it helpful?

Solution

Replace sprintf_s with vsprintf(and remove size) or with vsprintf_s if available.

Quoting from manpage of printf. (Emphasis mine)

The functions vprintf(), vfprintf(), vsprintf(), vsnprintf() are equivalent to the functions printf(), fprintf(), sprintf(), snprintf(), respectively, except that they are called with a va_list instead of a variable number of arguments. These functions do not call the va_end macro. Because they invoke the va_arg macro, the value of ap is undefined after the call.

Licensed under: CC-BY-SA with attribution
Not affiliated with StackOverflow
scroll top