Программирование AVR alloca: динамическое выделение памяти в стеке Thu, November 21 2024  

Поделиться

Нашли опечатку?

Пожалуйста, сообщите об этом - просто выделите ошибочное слово или фразу и нажмите Shift Enter.


alloca: динамическое выделение памяти в стеке Печать
Добавил(а) microsin   

Известно, что локальные переменные (и параметры) функций хранятся в стеке, и поэтому автоматически уничтожаются после завершения работы этой функции. Количество выделяемой памяти в стеке для этих целей определяется в момент компиляции, и при выполнении программы фиксировано. К счастью, компилятор gcc и его библиотеки поддерживает удобную возможность динамически выделять память за счет стека с помощью alloca.

[Достоинства alloca]

Вот основной список причин, почему бывает предпочтительно использовать alloca вместо кучи (т. е. вместо malloc [2]):

• Использование alloca очень мало занимает места под код, и этот код работает исключительно быстро.
• Поскольку у alloca нет отдельного пула для разного размера блоков, используемое пространство для блоков любого размера может повторно использоваться для любого другого размера. Вызов alloca не приводит к фрагментации памяти, что часто является проблемой для malloc, когда интенсивно выделяются блоки разных размеров.
• Не локальные выходы из функции с помощью дальнего перехода (longjmp) автоматически освободит место, выделенное alloca, когда происходит выход из функции, которая вызвала alloca. Это одна из самых важных причин использования alloca.

[Пример использования alloca]

В качестве примера использования alloca здесь приведена функция, которая открывает файл, имя которого склеивается из двух строк, указанных в аргументах, и возвращает дескриптор файла, или вернет -1, если открыть файл не получилось:

Чтобы показать это достоинства alloc, давайте предположим, что у Вас есть функция open_or_report_error наподобие open, которая возвратит дескриптор в случае успешного завершения, но не выполнит возврат в вызывающую функцию, если вызов был неудачен. Если файл не может быть открыт, то эта функция печатает сообщение об ошибке и выйдет на уровень команд вашей программы с помощью longjmp.

int open2 (char *str1, char *str2, int flags, int mode)
{
   char *name = (char *) malloc (strlen (str1) + strlen (str2) + 1);
   int desc;
   if (name == 0)
      fatal ("virtual memory exceeded");
   stpcpy (stpcpy (name, str1), str2);
   desc = open (name, flags, mode);
   free (name);
   return desc;
}

Давайте поменяем open2 для использования этой подпрограммы open_or_report_error:

int open2 (char *str1, char *str2, int flags, int mode)
{
   char *name = (char *) alloca (strlen (str1) + strlen (str2) + 1);
   stpcpy (stpcpy (name, str1), str2);
   return open_or_report_error (name, flags, mode);
}

Из-за принципа работы alloca та память, которую она выделила, освободится автоматически даже когда произойдет ошибка, и для этого не нужно делать никаких специальных усилий.

В отличие от предыдущего определения open2 (которое использует malloc и free), могла бы произойти утечка памяти, если изменить функцию таким же образом. Даже если Вы готовы внести больше изменений в malloc-реализацию с целью исправления ситуации, сделать это будет довольно непросто.

Как можно увидеть, на основе alloca реализация намного проще. В большинстве встраиваемых систем с маломощными микроконтроллерами у alloca нет разумной альтернативы. Однако надо иметь в виду, что несмотря на все свои достоинства, использование alloca имеет и недостатки.

[Недостатки alloca]

Недостатки alloca в сравнении с malloc:

• Если Вы попытаетесь выделить больше памяти, чем может предоставить машина, то не получите ясное сообщение об ошибке. Вместо этого скорее всего получится сигнал фатального сбоя, который происходит в случае бесконечной рекурсии. В мире PC возможно это будет сообщение о нарушении доступа к сегменту памяти. С микроконтроллерами это будет или исключение при недопустимой операции, или банальное зависание.
• Некоторые не GNU системы не поддерживают alloca, так что программы на основе alloca будет сложнее портировать. Однако в системах с таким недостатком можно использовать несколько более медленную эмуляцию alloca, написанную на языке C. 

[Ссылки]

1. Advantages of alloca site:gnu.org.
2AVR GCC: области памяти и использование malloc().

 

Добавить комментарий


Защитный код
Обновить

Top of Page