Статическое распределение всегда безопасно во время выполнения, так как, если у вас не хватает памяти, ваш компоновщик сообщит вам во время выполнения, а не сбой кода во время выполнения.Однако, если память не требуется постоянно во время выполнения, это может быть расточительным, поскольку выделенная память не может быть повторно использована для нескольких целей, если вы явно не закодируете ее таким образом.
Динамическое выделение памяти можно проверить во время выполнения- если у вас заканчивается куча, malloc () возвращает нулевой указатель.Однако вам необходимо проверить возвращаемое значение и освободить память при необходимости.Блоки динамической памяти обычно выровнены на 4 или 8 байтов и несут служебные данные управления кучей, что делает их неэффективными для очень небольших выделений.Кроме того, частое выделение и освобождение блоков с очень разными размерами может привести к фрагментации кучи и потере памяти - это может иметь катастрофические последствия для постоянно работающих приложений.Если вы никогда не намереваетесь освободить память, и она всегда будет распределена, и вы знаете, apriori , сколько вам нужно, тогда вам может быть лучше статическое распределение.Если у вас есть источник библиотеки, вы можете изменить malloc для немедленной остановки при сбое выделения памяти, чтобы избежать необходимости проверять каждое выделение.Если размеры распределений обычно имеют несколько общих размеров, предпочтительнее использовать распределитель с фиксированными блоками, а не стандартный malloc ().Это было бы более детерминировано, и вы могли бы реализовать мониторинг использования, чтобы помочь оптимизации размеров блоков и чисел каждого размера.
Распределение стека является наиболее эффективным, поскольку оно автоматически получает и возвращает память по мере необходимости.Однако он также имеет небольшую поддержку или вообще не поддерживает проверку во время выполнения.Как правило, когда происходит переполнение стека, код не будет детерминированно - и не обязательно где-то рядом с основной причиной.Некоторые компоновщики могут генерировать вывод анализа стека, который будет вычислять использование стека наихудшего случая через дерево вызовов;Вы должны использовать это, если у вас есть такая возможность, но помните, что если у вас многопоточная система, будет несколько стеков, и вам не нужно проверять наихудший случай для точки входа в каждую.Кроме того, lonker не будет анализировать использование стека прерываний, и ваша система может иметь отдельный стек прерываний или совместно использовать системный стек.
Способ, которым я бы занялся, безусловно, заключается в том, чтобы не размещать большие массивы или объекты в стеке.но выполните следующий процесс:
Используйте анализ стека компоновщика для расчета использования стека наихудшего случая, при необходимости добавьте дополнительный стек для ISR.Выделите столько стека.
Статически выделите все объекты, необходимые для выполнения.
- Используйте карту ссылок, чтобы определить, сколько памяти осталось, выделить почтивсе это в кучу (ваш компоновщик или скрипт компоновщика может делать это автоматически, но если вам нужно явно установить размер кучи, оставьте немного неиспользованным, в противном случае каждый раз, когда вы добавляете новый статический объект или расширяете стек, у вас будетизменить размер кучи).Выделите все большие временные объекты из кучи и будьте бдительны в отношении освобождения выделенной памяти.
Если в вашей библиотеке есть функции диагностики кучи, вы можете использовать их в своем коде для мониторинга использования кучи, чтобы проверить, насколько близковы до истощения.
Анализ линкера "наихудший случай", скорее всего, будет больше, чем вы видите на практике - наихудшие пути никогда не будут выполнены.Вы можете предварительно заполнить стек определенным байтом (скажем, 0xEE) или шаблоном, а затем после тщательного тестирования и работы проверить наличие отметки «high-tide» и оптимизировать стек таким образом.Используйте эту технику с осторожностью;Ваше тестирование может не охватывать все возможные обстоятельства.