размеры буфера sprintf - PullRequest
       19

размеры буфера sprintf

3 голосов
/ 30 октября 2011

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

Я пытаюсь напечатать числа в C. У меня есть функция, чтобы сделать это, используя sprintf. Числа никогда не должны быть больше 2 цифр, поэтому я использую 2-символьный буфер. Почему-то здесь моя логика терпит неудачу, потому что это вызывает бесконечный цикл, изменяя одну из переменных, передаваемых в sprintf, но увеличение размера буфера решает проблему.

Вот код ошибки:

#include <stdio.h>

void printarray(int array[][4]) {
  int y;
  int z;
  char buf[2];
  for (y=0; y<4; y++) {
    for (z=0; z<4; z++) {
      sprintf(buf, "%d", array[y][z]);
      printf("buf is %s, y is %d and z is %d\n",buf,y,z);
    }   
  }
}

int main() {
  int arr[4][4] = {  {1,2,3,4},{5,6,7,8},{9,10,11,12},{13,14,15,0}  };  

  printarray(arr);

  return 0;
}

как только у добирается до 2, оно возвращается к нулю, таким образом, бесконечный цикл. изменение buf [2] на buf [8] решает проблему.

Ответы [ 3 ]

12 голосов
/ 30 октября 2011

Вы забываете терминатор NUL. В C, строки требуют дополнительного символа для терминатора, поэтому char buf[2] должно быть char buf[3] для размещения чисел между 10 и 99.

Между прочим, ваш код демонстрирует, почему sprintf опасен, поскольку он может записывать за пределы выходного буфера и разрешать атаки с разбиванием стека . Лучшим вариантом является использование snprintf.

3 голосов
/ 30 октября 2011

C строки завершаются нулем. Если у вас есть 2 символа (например, «10»), вам нужен буфер размером 2 + 1 для нулевого терминатора.

sprintf() добавляет это в конец вашего буфера; в вашем текущем случае у вас фактически переполнение буфера, потому что вы не предоставляете достаточно места.

Современный, более безопасный подход - использовать snprintf(), для которого вы указываете длину буфера.

2 голосов
/ 30 октября 2011

Я предполагаю, что sprintf добавляет \0 в конце сгенерированной строки. Так, например, если вы напечатаете число 99, вы получите "99\0" в своем буфере, поэтому для буфера длиной 2 это вызывает проблемы.

...