【发布时间】:2015-01-13 05:16:22
【问题描述】:
This blog post 声称将va_list 传递给下面代码中的另一个函数是不安全的,并且必须首先使用va_copy 复制va_list:
void
foo_ap(const char *fmt, va_list ap)
{
char buf[128];
vsnprintf(buf, sizeof(buf), fmt, ap);
// now, do something with buf ...
}
就像博客文章中提到的其中一位 cmets 一样,我看不出这有多不安全,正如 C99 规范所述 (7.15):
对象
ap可以作为参数传递给另一个函数;如果该函数调用带有参数ap的va_arg宏,则调用函数中ap的值是不确定的,应在进一步引用ap之前将其传递给va_end宏。
(只要foo_ap 在传递它之后不引用ap,这句话的第二部分似乎无论如何都不适用。)博客文章的作者在另一条评论中说他可能错了,但也许有人可以添加一些说明。为了安全起见,我真的必须使用va_copy 吗?或者有没有平台不符合规范,需要使用va_copy?
【问题讨论】:
-
这篇博文似乎与您从 C99 标准中引用的条款直接矛盾。博客作者确实在开头说“很久以前”,所以我猜他正在处理一些旧的、不符合标准的系统。
-
如果您在
vsnprintf返回后仍打算使用ap,则只需要va_copy。例如,您可能想要调用vsnprintf两次——一次确定所需的缓冲区大小,然后再次进行格式化。如果你不需要再次使用ap,除了将它传递给va_end,那么你不需要va_copy它。 -
@IgorTandetnik 如果您将您的评论作为答案,我会接受。
标签: c language-lawyer c99 variadic-functions