вывод sprintf длиной от 9 до 12 байт в место назначения размером 9 - PullRequest
2 голосов
/ 08 ноября 2019

Я уже проверил эту проблему, но я не могу понять, как она применяется в моем случае.

При использовании

  char time[9];

  sprintf(time, "%2d:%2d:%2d",
          timestamp.Hour(),
          timestamp.Minute(),
          timestamp.Second());

я получаю предупреждение 'sprintf' output between 9 and 12 bytes into a destination of size 9 и

случайным образом перезагружаются на микроконтроллере, выполняющем код (если они как-то связаны).

Итак, откуда взялись эти дополнительные 3 байта? Как я могу это исправить?

Методы Hour (), Minute () и Second (), на самом деле возвращают uint8_t

Ответы [ 2 ]

5 голосов
/ 08 ноября 2019

Ваш компилятор, очевидно, знает, что значение uint8_t может давать от 1 до 3 цифр, но не то, что функции Hour, Minute и Second могут возвращать только до двухзначных значений.

Если вы передали значение 255 в формате "%2d", вы получите 3 символа. Если все три аргумента равны 100 или больше, вы бы записали 12 байтов в массив назначения. Компилятор предупреждает вас об ошибке, которая теоретически может произойти, учитывая типы аргументов, но, вероятно, не может произойти, учитывая фактические передаваемые значения. (Я несколько впечатлен тем, что он смог выдать это предупреждение, и не удивлен, что он не знает о семантике этих функций.)

Перезагрузка, вероятно, не связана. Попробуйте проверить содержимое time после вызова sprintf. Я думаю, вы обнаружите, что проблема не возникает там, и предупреждение является ложным. Вы можете отключить предупреждение, задав char time[12];, или просто проигнорировать предупреждение.

Эта диагностика производится gcc с опцией -Wformat-overflow=2, , задокументированной здесь .

1 голос
/ 08 ноября 2019

Очевидно, что любая правильно написанная функция, возвращающая часы, минуты и секунды (относительно текущей минуты), будет возвращать максимальное двузначное значение, но вы не можете ожидать, что ваш компилятор или анализатор узнают об этом. Размер типа, возвращаемого функцией , учитывается. Максимальное количество символов в 8-битном представлении с основанием 10 равно 3 (или 4, если оно подписано и отрицательно).

Кроме того, «2» в строке формата указывает минимальное числоколичество символов для печати, а не максимум.

Я бы порекомендовал увеличить размер буфера, чтобы приспособиться к этому, если только у вас недостаточно места на целевой платформе.

Если вы не можете получить большечем 9 байтов, попробуйте это:

char time[9];

sprintf(time, "%2d:%2d:%2d",
      min(timestamp.Hour(), 23),
      min(timestamp.Minute(), 59),
      min(timestamp.Second(), 59));
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...