Is va_end required after vsnprintf_s call?

MSDN shows this example code snippet for vsnprintf_s :

 // crt_vsnprintf_s.cpp #include <stdio.h> #include <wtypes.h> void FormatOutput(LPCSTR formatstring, ...) { int nSize = 0; char buff[10]; memset(buff, 0, sizeof(buff)); va_list args; va_start(args, formatstring); nSize = vsnprintf_s( buff, _countof(buff), _TRUNCATE, formatstring, args); printf("nSize: %d, buff: %s\n", nSize, buff); } int main() { FormatOutput("%s %s", "Hi", "there"); FormatOutput("%s %s", "Hi", "there!"); FormatOutput("%s %s", "Hi", "there!!"); } 

In this example, va_start is called without va_end matching.

Is this a document error on MSDN, or are we just calling va_start before calling vsnprintf_s , and then let this function do the cleanup (i.e. calling va_end ) for us?

BTW: I tried the above code and it works with VS2015 with Update 3, but I don't know if this behavior is just undefined ...

+7
c ++ c variadic-functions
source share
3 answers

va_end must be called for each va_start . From http://en.cppreference.com/w/c/variadic/va_end :

If there is no corresponding call to va_start or va_copy , or if va_end not called before the function returns va_start or va_copy , the behavior is undefined.

You not only need va_end , but you also need to make sure that your function does not return before va_end is executed if va_start or va_copy .

To answer your question - yes, this is a documentation error on MSDN.

+7
source share

From the MSDN page for va_arg , va_copy , va_end , va_start :

After all arguments have been received, va_end resets the pointer to ZERO. va_end must be called on each argument list that is initialized with va_start or va_copy before the function returns .

So this is a documentation error.

+3
source share

Assuming vsnprintf_s suppose it looks like vsnprintf , you should not expect it to call va_end() for you:

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

(my emphasis)

+1
source share

All Articles