vsnprintf_s呼叫后va_end需要
Is va_end required after a vsnprintf_s call?
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: %sn", nSize, buff); } int main() { FormatOutput("%s %s", "Hi", "there"); FormatOutput("%s %s", "Hi", "there!"); FormatOutput("%s %s", "Hi", "there!!"); }
在此示例中,调用va_start
时没有匹配的va_end
。
这是 MSDN 中的文档错误,还是我们应该在调用vsnprintf_s
之前调用va_start
,然后让此函数为我们进行清理(即调用 va_end
(?
顺便说一句:我尝试了上面的代码,它适用于带有更新 2015 的 VS3,但我不知道它是否只是未定义的行为......
为每个va_start
调用va_end
。从 http://en.cppreference.com/w/c/variadic/va_end:
如果没有对
va_start
或va_copy
的相应调用,或者在调用va_start
或va_copy
返回的函数之前未调用va_end
,则行为是未定义的。
您不仅需要va_end
还需要确保在执行va_end
之前不会返回函数,如果执行va_start
或va_copy
。
回答您的问题 - 是的,这是 MSDN 中的一个文档错误。
从 MSDN 页面的 va_arg
, va_copy
, va_end
, va_start
:
检索完所有参数后,
va_end
将指针重置为 零。 必须在初始化的每个参数列表上调用va_end
在函数返回之前va_start
或va_copy
。
所以是的,这是一个文档错误。
假设vsnprintf_s
应该类似于vsnprintf
,那么你不应该期望它为你调用va_end()
:
函数
vprintf()
、vfprintf()
、vdprintf()
、vsprintf()
、vsnprintf()
分别等价于函数printf()
、fprintf()
、dprintf()
、sprintf()
、snprintf()
,只是它们被调用时带有va_list
而不是可变数量的参数。 这些函数不调用va_end
宏。 由于它们调用va_arg
宏,因此在调用后未定义ap
的值。 请参阅stdarg(3)
。
(我的强调(
- 来自 std::list 的迭代器 .end() 按预期返回"0xcdcdcdcdcdcdcdcd"但 .begin()
- std::map<struct,struct>::find 找不到匹配项,但是如果我循环通过 begin() 到 end(),我在那里看到匹配项
- std::原子加载和存储都需要吗
- 需要帮助设置在C++中使用的Potrace
- 是否需要删除包含对象的"pair"?
- Arduino:for/while/if在void setup()或void loop()之前?——错误:之前需要不合格
- C++我需要了解在哪里使用指针和双指针
- 为什么即使使用-cudart-static进行编译,库用户仍然需要链接到cuda运行时
- 这个指针和内存代码打印是什么?我不知道是打印垃圾还是如何打印我需要的值
- 在两个类中共享相同的函数调用,并在不需要时避免空实例化
- 当使用透明的std函数对象时,我们还需要写空的尖括号吗
- 我需要将多个函数组合为一个函数
- 概念中的cv限定符需要表达式参数列表
- 是否有类似std::lower_bound的函数,而不需要排序/分区输入
- 库函数需要一个 std::function<void(void)>,如何传入类函数?
- 需要从 istream 和 ostream 派生 iostream
- 我需要知道编译器如何在cpp中使用析构函数
- 我当前实现的双向链表类是否需要重构迭代器 end() 功能?
- 为什么在查找元素时需要使用 set.find(x) != set.end()
- 为什么需要它!=obj.end() 尽管每个迭代器都应该知道自己何时终止