Предупреждение "формат не строковый литерал и аргументы формата" не отображаются в последней версии gcc
В моем коде я использую следующую строку для печати char readbuffer[1];
массив (массив символов с размером 1):
printf(readbuffer);
Это компилируется и работает без проблем на моем компьютере (Arch Linux, gcc версия 7.3.1+20180406-1
). Однако, когда я отправил свое назначение, содержащее этот код, моему инструктору, он фактически получил предупреждение компилятора, компилирующее мой код:
shell.c:89:20: warning: format not a string literal and no format arguments [-Wformat-security]
printf(readbuffer);
Он использует версию gcc/clang от 16.04 выпуска LTS. Мы оба использовали одни и те же флаги компилятора.
Почему это? Разве это не проблема больше не в новом gcc
версия? Если так, то почему бы и нет?
Просто примечание: я не хочу знать, как решить эту проблему, но просто хочу знать, почему предупреждение несовместимо с версиями gcc.
2 ответа
Это не вызвано разницей в версиях GCC. Скорее Ubuntu изменил GCC, чтобы включить -Wformat -Wformat-security
по умолчанию Если вы передадите эти параметры в Arch Linux, вы должны увидеть там то же самое поведение.
Я не хочу знать, как решить эту проблему...
Да, вы действительно делаете!
Если только ваш char[1]
переменная всегда содержит \0
То, что вы делаете, небезопасно. А также. если он содержит это, то, что вы делаете, ничего не значит:-)
Правильный способ сделать то, что вы пытаетесь сделать, это при условии необходимости printf
:
printf("%.1s", readbuffer);
Это гарантирует, что вы не будете пытаться читать дальше этого единственного символа. Конечно, если вы знаете, что всегда будет персонаж, просто используйте:
putchar(*readbuffer);
С точки зрения того, почему разные gcc
версии сообщают по-разному, что можно со временем объяснить простым улучшением. Это та же самая причина, почему, например, gcc
будет жаловаться на несоответствие между количеством спецификаторов формата и количеством аргументов в чем-то вроде:
printf ("%s %d\n", "hello");
тогда как некоторые другие реализации не могут.
В частности, в то время как стандарт предписывает то, что должно быть сообщено как диагностику, он не ограничивает иначе, что реализации могут сообщать как диагностику за пределами этого.
Более поздние версии компилятора могут добавлять или удалять эти необязательные диагностические данные или изменять то, как они решают сообщать о них.