Ложное чувство безопасности с `snprintf_s`

«Безопасные» функции sprintf MSVC имеют версию шаблона, которая «знает» размер целевого буфера. Однако этот код успешно рисует 567890 поверх стека после окончания bytes...

char bytes[5];
_snprintf_s( bytes, _TRUNCATE, "%s", "1234567890" );

Любая идея, что я делаю неправильно, или это известная ошибка?

(Я работаю в VS2005 - не тестировал в 2008 или 2010)


person xtofl    schedule 29.04.2010    source источник
comment
Ой! Это неловко.   -  person bobince    schedule 29.04.2010


Ответы (3)


Похоже, это ошибка в Visual C++ 2005 (у меня проблемы с доступом к этой ссылке; Google также он кэширован).

Мне удалось воспроизвести проблему в Visual C++ 2005. В Visual C++ 2008 и 2010 строка усекается правильно (bytes содержит 1234\0), а -1 возвращается, как и ожидалось.

person James McNellis    schedule 29.04.2010
comment
Спасибо! Кажется, отчет об ошибке действительно исчез с сайта MS Connect... - person xtofl; 30.04.2010

Пример действительно правильный. По версии --

Microsoft Visual Studio 2005
Version 8.0.50727.867 (vsvista.050727-8600)
...
Visual C++ 77626-009-0000007-41722

-- который включает в себя SP1, исправление для Vista и несколько исправлений библиотеки -- упомянутая выше функция

template <size_t size>
int _snprintf_s(
   char (&buffer)[size],
   size_t count,
   const char *format [,
      argument] ... 
);

все еще содержит ошибки. Однако, что действительно интересно, так это то, что только эта функция из 4 вариантов работает

  • OK: int _snprintf_s(char *buffer, size_t sizeOfBuffer, size_t count, :::
  • Багги: template <size_t size> int _snprintf_s(char (&buffer)[size], size_t count, :::
  • OK: int _snwprintf_s (широкосимвольная версия)
  • OK: template <size_t size> int _snwprintf_s (да, широкоформатная версия подходит)

глючит, то есть если вы используете версию без шаблона, все в порядке, и если вы используете любую из версий с широкими символами, это тоже нормально. Удивительно.

person Martin Ba    schedule 25.10.2012

Пример был неправильным.

Код должен быть:

char bytes[5];
_snprintf_s( bytes, 5, _TRUNCATE, "%s", "1234567890" );

Для неправильного кода может быть ошибка, что компилятор не выдает никаких предупреждений, но это будет слабая проверка для snprintf.

person sst    schedule 02.02.2012
comment
-1: вопрос, который является старым и на который дан ответ, говорит о перегрузке _snprintf_s, которая принимает массив char для записи. Ему не нужно принимать размер, потому что он может получить размер из параметра шаблона. За исключением того, что в VC 2005 это было сломано. - person Nicol Bolas; 03.02.2012