If a C programmer asks "do you want to see something cool?", run away.
--John Van Enk

Tuesday, November 6, 2007

О чем молчит printf

Недавно, читая книгу Диомидиса Спинеллиса "Анализ программного кода на примере проектов Open Source", узнал что функция printf возвращает результат - количество фактически выведенных символов. Посмотрел в мане и стандарте на язык С - таки да "The printf function returns the number of characters transmitted, or a negative value if an output or encoding error occurred". А я то всегда думал что она void. И практически повсеместно встречал ее использование без проверки возвращаемого значения. К чему это может привести? Это может привести к тому, что в ходе выполнения программы может возникнуть ошибка, которая пройдет незамеченной (в лучшем случае).
Вообще все функции вывода - в частности, при перенаправлении стандартного потока вывода в файл - могут завершиться аварийно по целому ряду причин:
  • на устройстве, куда перенаправляется вывод, может не хватить свободного места
  • может исчерпаться квота пользователя на объем дискового пространства
  • процесс может попытаться записать файл, который превысит максимально допустимый для этого процесса или системы объем
  • на устройстве может произойти аппаратная ошибка
  • дескриптор файла или потока, ассоциированного со стандартным потоком вывода, может оказаться не разрешенным для записи
Без проверки успешности вывода программа может тихо и незаметно рухнуть с потерей всех выводимых данных. Однако проверять результат каждой операции вывода - неудобно, поэтому зачастую используется компромиссный подход - проверка ошибок вывода в поток перед завершением программы. В языке С для этого есть функция ferror:

if (ferror(stdout))
err(1, "stdout");


Функция err - это нестандартное BSD расширение для выдачи форматированных сообщений об ошибках.

Так, что подобные очевидные моменты не стоит недооценивать...

Upd: благодаря комментарию Сергея Кондрикова - вот ссылка на очень хорошую статью в Википедии: Printf. В ней, помимо всего прочего, довольно подробно описаны уязвимости функции и возможные последствия.