我有一个带有可变参数的函数,用于记录日志。在对传递的缓冲区进行一些自定义操作之后,它会调用_vsnprintf_s格式化缓冲区。我们的一位客户最近通过了内部带有单个百分比的格式字符串,并且使用VS 2017构建的应用程序(其中CRT驻留在ucrtbase.dll中)崩溃了,而仅使用VS 2013构建的同一应用程序中的相同功能能够处理该问题。格式字符串为:
"...10% text..."
尽管我同意格式字符串不正确,但让我担心的是,使用VS 2013构建的应用程序在某种程度上对其进行了处理,并且输出为:
"...10 ..."
因此在使用VS 2017构建的应用程序崩溃时不会冒犯%。我尝试在std14和std17之间切换-没什么区别。我目前正在使用std17。调试时,我注意到它在这里失败:
_Success_(return >= 0)
_Check_return_opt_ _CRT_INSECURE_DEPRECATE(_vsnprintf_s_l)
_CRT_STDIO_INLINE int __CRTDECL _vsnprintf_l(
_Out_writes_opt_(_BufferCount) _Post_maybez_ char* const _Buffer,
_In_ size_t const _BufferCount,
_In_z_ _Printf_format_string_params_(2) char const* const _Format,
_In_opt_ _locale_t const _Locale,
va_list _ArgList
)
#if defined _NO_CRT_STDIO_INLINE
;
#else
{
int const _Result = __stdio_common_vsprintf(
_CRT_INTERNAL_LOCAL_PRINTF_OPTIONS | _CRT_INTERNAL_PRINTF_LEGACY_VSPRINTF_NULL_TERMINATION,
_Buffer, _BufferCount, _Format, _Locale, _ArgList);
return _Result < 0 ? -1 : _Result;
}
#endif
有消息
Expression: _length == length_modifier::none
但是在发布模式下它崩溃了。这告诉我,在处理格式字符串中使用不正确的百分比方面,CRT实现可能发生了变化。解决方案是先扫描整个格式字符串,然后再传递它-但我想避免使用它,因为这样做会大大降低速度。我尝试使用StringCchVPrintfEx,但事实证明,它最终调用了相同的方法。我很乐意提出建议。