vxxxxf 系列函数会修改 args
2014年4月7日
2 条评论
之前碰到过一次,结果 de 完 bug 转头就忘了。
于是今天就又花了半天来 de 这个 bug。
vxxxxf 包括 vsnprintf 等等等等。
C99 / C++11 有一个新的宏 va_copy,可以制造一个 args 的副本,然后每次调用 vxxxxf 之前传副本进去就好。
ref: http://en.cppreference.com/w/cpp/utility/variadic/va_copy
一个例子(把 vsnprintf 通过返回值返回错误改成了通过异常指示错误):
size_t string_printf(
char *buffer,
size_t buffer_size,
const char *format,
va_list args
)
{
//
// args 第一次用于 vsnprintf 计算所需要的字符数,由于 vsnprintf
// 可能会修改 args(实际上确实修改了),所以要搞一个副本给第一次
// 的 vsnprintf 做参数。
//
va_list args_copy;
va_copy(args_copy, args);
BOOST_SCOPE_EXIT(&args_copy)
{
va_end(args_copy);
}
BOOST_SCOPE_EXIT_END;
int cch_needed = vsnprintf(nullptr, 0, format, args_copy);
if (cch_needed < 0)
{
throw std::runtime_error("vsnprintf failed.");
}
else if (static_cast<size_t>(cch_needed) > buffer_size - 1)
{
throw std::overflow_error("Buffer is too small.");
}
cch_needed = vsnprintf(buffer, buffer_size, format, args);
if (cch_needed < 0 || static_cast<size_t>(cch_needed) > buffer_size - 1)
{
throw std::runtime_error("Unexpected exception.");
}
return cch_needed;
}