使用安全_vsnprintf_s获取所需的缓冲区长度

Mah*_*dsi 5 c++ printf visual-c++-2015

我正在尝试更新一些"遗留"代码,以符合MSVC的最新安全更新,并且我正面临着迁移_vsnprintf到的一些问题_vsnprintf_s.

特别是,我_vsnprintf使用空缓冲区调用,为计数/长度调用零,获取结果,分配所需大小的缓冲区(return value + 1),然后_vsnprintf使用新分配的缓冲区和已知正确的大小再次调用:

size_t length = _vsntprintf(nullptr, 0, mask, params);
TCHAR *final = new TCHAR [length + 1];
_vsntprintf(final, length + 1, mask, params);
Run Code Online (Sandbox Code Playgroud)

MSDN记录了此行为:

如果count指定的缓冲区大小不足以包含format和argptr指定的输出,则vsnprintf的返回值是count(如果count足够大)将写入的字符数.如果返回值大于count-1,则输出已被截断.

我正在尝试做同样的事情_vsnprintf_s,但它的文档不包含相同的内容.相反,它说

如果存储数据和终止空值所需的存储超过sizeOfBuffer,则调用无效参数处理程序,如参数验证中所述,除非count为_TRUNCATE,在这种情况下,将写入适合缓冲区的字符串,并且 - 1回来了.

无论如何都要尝试以下内容:

size_t length = _vsntprintf_s(nullptr, 0, 0, mask, params);
Run Code Online (Sandbox Code Playgroud)

这导致"长度"为零.如果您传入_TRUNCATE(-1)作为计数,则以下断言失败:

表达式:buffer!= nullptr && buffer_count> 0

我认为可以覆盖_set_invalid_parameter_handler并以某种方式找出长度应该是多少,但是必须有一种更简单的方法吗?

Tri*_*lJM 8

size_t length = _vscprintf(mask, va_list);
TCHAR *final = new TCHAR [length + 1];
_vsntprintf_s(final, length, _TRUNCATE, mask, va_list);
Run Code Online (Sandbox Code Playgroud)

  • 那是完美的.一个漂亮,干净的解决方案 `_vscprintf`应记录在`_vsnprintf_s`页面上,imho. (2认同)