Ардуино УНО, ATMEGA328PU
Компилятор выдает такое сообщение:
Скетч использует 13522 байт (41%) памяти устройства. Всего доступно 32256 байт.
Глобальные переменные используют 1583 байт (77%) динамической памяти, оставляя 465 байт для локальных переменных. Максимум: 2048 байт.
Недостаточно памяти, программа может работать нестабильно.
Вопрос: На основе чего компилятор решает, что недостаточно памяти?
Это какой-то серьезный анализ кода, в котором производится вычисление максимальной глубины использования стека и прочей необходимой памяти или просто тупое сообщение о том что свободной памяти осталось менее определенного процента?
Если программист точно знает, что он делает и зачем, любое предупреждение для него будет бесполезным. А если программист признает за собой возможность ошибки, то любое предупреждение может (но не обязано) оказаться полезным.
Ну вообще-то у меня есть экранный буфер размером 640 байт, ну и кроме того еще используется библиотека для работы с SD-картой. Все остальное там по мелочи.
Поначалу думал что если это сообщение о нехватке памяти серьезное - то переделаю вывод на дисплей и сокращу экранный буфер до чуть более 100 байт. (ну т.е. сделав его не графическим, а символьным). Но так делать не хотелось бы по той причине, что текст уже не получится вывести куда угодно, а только по знакоместам, ну и кроме того не получится использовать пропорциональный шрифт. Но судя по ответам решил пока не заморачиваться уменьшением буфера.
А вообще как можно приблизительно оценить РЕАЛЬНОЕ наименьшее возможное кол-во свободной памяти?
Например можно ли в произвольный момент узнать адрес, где начинается свободная память?
Все верно, именно это я и имею ввиду.
Т.е. к примеру нахожу разницу между вершиной стека и кучей. Это будет размером свободной памяти. Сравниваю это значение с сохраненным, если оно меньше, то заменяю сохраненное. Полученную подпрограмму вешаю на прерывание по таймеру, настраиваю таймер, чтобы он срабатывал как можно чаще, но в то же время оставлял возможность работы основной программе.
Ну и через какое-то значительное время считываю получившееся значение и вывожу куда-нить.
Только как узнать адрес где заканчивается куча?
На разных платформах определены разные имена, поэтому наиболее универсальный метод - запросить память в куче (запомнив адрес), после чего освободить ее.
Ну, во-первых, можно попытаться сделать так, чтобы было всегда. Например, сделать несколько итераций с разным объемом запрашиваемой памяти.
А во-вторых, это в большей степени зависит от характера работы с памятью: можно ведь и просто не допускать фрагментирования памяти.
Ну и никогда не следует забывать, что Arduino - это не только AVR.
Кстати, а что вообще выдает __heap_start/__heap_end при фрагменитированной памяти?
malloc и так проверяет будет ли затирание стека и возвращает 0, если требуемый кусок уже пересекает нижнюю границу стека…
А если “писатель” устроил рекурсию или просто организовал в стеке большой массив и затер верхушку кучи, то тут уже ничего не поможет…