У меня есть следующий код, скомпилированный с помощью компилятора Microchip MPLab и XC8 и работающий на PIC18F2550, который делает что-то довольно странное:
char output[20];
int i = 0;
char currentStatus = readShiftReg();
for (i = 0; i < 8; i++) {
if ((currentStatus & (1 << i)) == (1 << i))
sprintf(output, "Sensor %d is currently on \r\n", i + 1);
else
sprintf(output, "Sensor %d is currently off \r\n", i + 1);
putsUSART(output);
}
Цикл for выполняется только один раз, и во время этой итерации он правильно выполняет второй sprintf
, но после его запуска значение i
является чем-то случайным (26154, 8294,...). Я попытался заменить i
другую переменную, j
присваивающую значение i
to j
в начале цикла, но то же самое происходит и с i
.
Кажется, что-то с этим sprintf
, потому что, когда я использую отладчик, значение i
не изменяется до тех пор, пока не sprint
будет выполнено. Следует отметить, что значение на выходе правильное (т. е. «Датчик 0 в настоящее время выключен \r\n»), что делает это еще более запутанным.
Это должен быть очень простой фрагмент кода, но он не работает, и я уверен, что этому есть простое объяснение. Где я должен искать?
Ваша проблема в этой строке:
char output[20];
Вы выделяете 20 символов для буфера для хранения вашей строки, а затем вызываете sprintf() для его заполнения.
Однако ваша строка формата слишком длинная, даже до включения десятичного значения. Помня, что последним элементом массива всегда должен быть \x00
(символ NUL), у вас есть 19 символов для использования в вашем сообщении.
Подсчитайте количество символов в этой строке:
Датчик %d в настоящее время выключен\r\n
Всего 29 символов (при условии двузначного числа). Это приводит к переполнению буфера, что приводит к затиранию других переменных и может привести к тому, что ваша программа будет работать непредвиденным образом. Это один из распространенных типов проблем безопасности в C.
Увеличьте размер вашего буфера, чтобы он был достаточно большим, чтобы содержать:
i
когда-либо будет храниться в переменной.\r\n
.Ваше char output
объявление слишком маленькое для строки, которую вы хотите записать.
Попробуйте еще раз сchar output[50]
Ваша переменная count i
сохраняется непосредственно за последней переменной массива символов.
Что-то вроде этого:
Adress Value
0x0F00 char[0]
0x0F01 char[1]
. .
. .
. .
0x0F19 char[19] <-- last variable of char
0x0F20 i <-- counter variable
Теперь sprintf не проверяет длину массива, в который он записывает. Проверяйте длину массива перед записью в код!
Мэтт Руве
Маженко