[an error occurred while processing this directive]
|
Зачем нужна куча (heap)
В "большом" программировании модно использовать динамическое распределение памяти. Для этих целей используется специальная структура - куча ("heap"). В "больших" компьютерах управлением этой кучей обычно занимается операционная система. В микроконтроллерах, где операционной системы нет, компилятор создает для кучи специальный сегмент. Кроме того, в стандартные библиотеки включены функции malloc и free для выделения и освобождения памяти соответственно.Что ж использовать динамическое распределение памяти иногда удобно... Однако, как я уже говорил, за такие удобства приходится дорого платить. А в случае и без того ограниченных ресурсов, цена может быть просто фатальной.
Посмотрим, какова цена использования кучи в AVR-GCC 3.3. Напишем простейшую программу БЕЗ динамического распределения памяти.
char a[100];
void main(void)
{
a[30]=77;
}Как и следовало ожидать, код получился очень компактный (я компилировал с ключом "-O3"). Запись в массив выполняется одной командой за два такта. (Ведь адрес каждого элемента заранее известен).
Результаты: Память программ - 50 слов (вместе с векторами прерываний, "startup"-кодом и т.д). Память данных - 100 байт (кроме массива там ничего нет). Функция main() выполняется за 9 тактов (вместе с инициализацией стека и выходом).
Теперь сделаем то же самое, разместив массив в куче.
char * a;
void main(void)
{
a=malloc(100);
a[30]=77;
free(a);
}Результаты: Память программ - 325 слов. Память данных - 114 байт (при размещенном массиве). Запись в массив выполняется пятью командами за шесть тактов. Функция "main" выполняется за 147 тактов (вместе с инициализацией стека и выходом).
Программа выросла аж на 275 слов. Из них функция "malloc" занимает 157 слов и функция "free" - 104 слова. Остальные 14 слов занимают вызовы "malloc" и "free", более сложная процедура обращения к массиву и данные для инициализации кучи.
Лишние 14 байт памяти данных занимают переменные для организации кучи (10 байт), сам указатель на массив "a" (2 байта), кроме того функция "malloc" резервирует 2 байта перед выделенным блоком, в которых хранится длина этого блока. Это нужно, чтобы корректно выполнить операцию "free".
Выводы...
Динамическое распределение памяти, хотя и упрощает написание программы, очень усложняет (и замедляет) ее исполнение. В микроконтроллерах, когда нет понятия "пользовательская" задача, а ресурсы ограничены, применение динамического выделения памяти неоправдано.Действительно, если про задачи все известно заранее, значит заранее можно определить и требования к памяти (хотя бы максимальные).
Я ни разу не встречал случая, когда от кучи было бы невозможно избавиться. Более того, мне трудно даже представить такой случай :))).
Поправьте меня, если я не прав.Некоторые способы "избавления" от кучи я попытаюсь описать на следующих страницах...
Продолжение следует...