Как определить соответствующие размеры стека и кучи для ARM Cortex, используя C++

файл запуска процессора cortex M3 позволяет указать объем ОЗУ, выделенный для стека и кучи. Для базы кода на c++ существует ли общее эмпирическое правило или, возможно, более явный способ определения значений для размеров стека и кучи? Например, вы могли бы подсчитать количество и размер уникальных объектов или, возможно, использовать размер скомпилированного кода?

4 ответов


файл запуска процессора cortex M3 позволяет указать количество ОЗУ, посвященная стеку и куча.

это не особенность Cortex-M3, а скорее код запуска, предоставляемый вашей цепочкой инструментов разработки. Это способ запуска файлов Keil ARM-MDK по умолчанию для работы M3. Это немного необычно; чаще всего вы указываете размер стека и любую оставшуюся память после размещения стека и статической памяти компоновщиком становится кучей; это, возможно, лучше, так как вы не в конечном итоге с пулом непригодной памяти. Вы можете изменить это и использовать альтернативную схему, но вам нужно знать, что вы делаете.

если вы are используя Keil ARM-MDK, параметры компоновщика -- info=stack и --callgraph добавляют информацию в файл карты, который помогает анализу требований стека. Эти и другие техники описаны здесь.

если вы используете RTOS или многозадачное ядро, каждая задача будет иметь свой собственный стек. ОС может предоставлять инструменты анализа стека, средство просмотра ядра RTX Keil показывает текущее использование стека, но не пиковое использование стека (поэтому в основном бесполезно, и оно работает только для задач с длиной стека по умолчанию).

Если вам нужно реализовать инструменты проверки стека самостоятельно, обычным методом является заполнение стека известным значением и, начиная с высокого адреса, проверьте значение, пока не найдете первое значение, которое не является заполните байт, это даст метку высокого прилива likley стека. Для этого можно реализовать код или вручную заполнить память отладчика, а затем отслеживать использование стека в окне памяти отладчика.

требование к куче будет зависеть от поведения вашего кода во время выполнения; вам придется проанализировать это самостоятельно, однако в ARM/Keil Realview обработчик исключений MemManage будет вызываться, когда c++'s new выбрасывает исключение; я не уверен, если malloc() или просто возвращает NULL. Можно поместить точку останова в обработчик исключений или изменить обработчик, чтобы выдать сообщение об ошибке для обнаружения исчерпания кучи во время тестирования. Существует также a __heapstats() функция, которая может использоваться для вывода информации куча. Он имеет несколько громоздкий интерфейс, я завернул его так:

void heapinfo()
{
typedef int (*__heapprt)(void *, char const *, ...);
    __heapstats( (__heapprt)std::fprintf, stdout ) ;
}

размер скомпилированного кода не поможет, так как код не запускается ни в стеке, ни в куче. Устройства Cortex-M3 обычно реализуются на микроконтроллерах со встроенной вспышкой и относительно небольшим объемом оперативной памяти. В этой конфигурации код обычно запускается из Flash.

куча используется для динамического выделения памяти. Подсчет числа уникальных объекты даст вам приблизительную оценку, но вы также должны учитывать любые другие элементы, которые используют динамическую память распределение (используя new ключевое слово в C++). Как правило, динамическое распределение памяти избегается во встроенных системах по той причине, что размер кучи трудно управлять.

стек будет использоваться для передачи переменных, локальных переменных и сохранения контекста во время процедур обработки исключений. Обычно трудно получить хорошее представление об использовании стека, если код не выделяет большой блок локальной памяти или большие объекты. Один из методов, который может помочь, - это выделить все доступной оперативной памяти для стека. Заполните стек известным шаблоном (0x00 или 0xff-не лучший выбор, так как эти значения часто встречаются), запустите систему на некоторое время, а затем просмотрите стек, чтобы узнать, сколько было использовано. По общему признанию, это не очень точный и научный подход, но все же полезный во многих случаях.


последняя версия компилятора IAR имеет функцию, которая определит, какой размер стека вам нужен, на основе статического анализа вашего кода (при условии, что у вас нет рекурсии).

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


сокращение до сбоя-это быстрый способ ad-hoc. Вы также можете заполнить стек известным значением, скажем, 0xCCCC, а затем отслеживать максимальное использование стека путем сканирования для 0xCCCC. Это несовершенно, но гораздо лучше, чем искать аварию.

обоснование того, что уменьшение размера стека не гарантирует, что переполнение стека будет жевать что-то "видимое".