Прямо сейчас я нахожусь в командировке в Беларуси, и поймал странное поведение программы, проявляющееся после 20-30 секунд работы девайса на STM32.
У меня в программе есть энумератор, который может принимать только три значения, от 0 до 2:
Однако, при отладке оказалось что в этой переменная лежит 0x72, вот скриншот окна Watch:
Как так? Ещё и на осциллографе какая-то фигня вместо нормальных посылок на UART, который обрабатывается вообще в другом месте кода.
Открываем map-файл. printer_type лежит по адресу 0x200002a3. Смотрим память.
Ясно, его затёр мусор, начинающийся примерно в 0x20000214. Опять смотрим map.
Вот он, массив databuf_BA.
Но он имеет длину 50.
Найдём, где массив заполняется. Так и есть, мы просто идём по массиву подряд, не проверяя границы.
Когда я писал это место, я надеялся что received_count (сбрасывающийся немного дальше) никогда не превысит не то, что 50, а даже 20. Зря надеялся, ошибки могут возникать везде.
Исправление, конечно, очень простое: нужно контролировать рост адреса в массиве выше какого-то безопасного значения меньше его размера.
Вот так, из-за характера расположения переменных в памяти, и того что C не контролирует переполнение — ошибка в одном месте портит что-то в совершенно другом месте. Это — классический пример сильной связности кода на C.
Свежие комментарии