VS 2017 _vsnprintf изменил поведение - PullRequest
0 голосов
/ 24 августа 2018

У меня есть функция с переменными аргументами, используемая для целей ведения журнала.После некоторых пользовательских манипуляций с переданным буфером он вызывает _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

Однако в режиме Release это происходило сбоем.Это говорит мне о том, что реализация CRT, вероятно, изменилась в отношении обработки неправильно используемого процента в строке формата.Решение состоит в том, чтобы сканировать всю строку формата до ее передачи - но я бы хотел этого избежать, потому что это значительно замедлило бы процесс.Я пытался использовать StringCchVPrintfEx, но оказалось, что он вызвал тот же метод.Я очень открыт для предложений.

...