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,但我不知道它是否只是未定义的行为...
答案 0 :(得分:7)
va_end
都需要调用 va_start
。来自http://en.cppreference.com/w/c/variadic/va_end:
如果没有对
va_start
或va_copy
的相应电话,或者在调用va_end
或va_start
的函数返回之前未调用va_copy
,行为未定义。
您不仅需要va_end
,而且还需要确保在执行va_end
或va_start
之前执行va_copy
之前您的函数不会返回。< / p>
回答你的问题 - 是的,这是MSDN中的文档错误。
答案 1 :(得分:3)
来自the MSDN page for va_arg
, va_copy
, va_end
, va_start
:
在检索完所有参数后,
va_end
将指针重置为 空值。必须在每个已初始化的参数列表上调用va_end
在函数返回之前使用va_start
或va_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)
。
(我的重点)