在vsnprintf_s调用之后是否需要va_end?

时间:2016-10-11 15:48:45

标签: c++ c variadic-functions

MSDN显示了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!!");
}

在此示例中,va_start被称为匹配va_end

这是MSDN中的doc bug,还是我们应该在调用va_start之前调用vsnprintf_s 然后让这个函数进行清理(即调用va_end对我们来说?

BTW:我尝试了上面的代码,它适用于VS2015和Update 3,但我不知道它是否只是未定义的行为...

3 个答案:

答案 0 :(得分:7)

每个va_end都需要调用

va_start。来自http://en.cppreference.com/w/c/variadic/va_end

  

如果没有对va_startva_copy的相应电话,或者在调用va_endva_start的函数返回之前未调用va_copy,行为未定义。

您不仅需要va_end,而且还需要确保在执行va_endva_start之前执行va_copy之前您的函数不会返回。< / p>

回答你的问题 - 是的,这是MSDN中的文档错误。

答案 1 :(得分:3)

来自the MSDN page for va_arg, va_copy, va_end, va_start

  

在检索完所有参数后,va_end将指针重置为   空值。必须在每个已初始化的参数列表上调用 va_end   在函数返回之前使用va_startva_copy

是的,这是一个文档错误。

答案 2 :(得分:1)

假设vsnprintf_s应该与vsnprintf类似,那么您不应期望它为您调用va_end()

  

函数vprintf()vfprintf()vdprintf()vsprintf()vsnprintf()等同于函数printf()fprintf()分别是dprintf()sprintf()snprintf(),除了用a调用它们          va_list而不是可变数量的参数。 这些函数不会调用va_end宏。因为它们调用va_arg宏,所以ap的值在调用后未定义。请参阅stdarg(3)

(我的重点)