Привет, Хабр! В последняя статья Я сам об этом упомянул, и в комментариях спросили - ок, окей, научным методом мы подобрали размер стека, вроде ничего не падает, но можно ли как-то более достоверно прикинуть, чему он равен а кто вообще столько сожрал? Короткий ответ: да, но нет. Нет, с помощью методов статического анализа невозможно точно измерить размер стека, необходимый программе — но, тем не менее, эти методы могут быть полезны.
Ответ чуть длиннее — под катом.
Как известно большинству людей, пространство стека по существу выделяется для локальных переменных, которые используются выполняющейся в данный момент функцией — за исключением переменных с модификатором static, которые хранятся в статически выделенной памяти, в области bss, поскольку они должны сохранять свои значения между вызовами функций.
При выполнении функции компилятор добавляет в стек место для необходимых ему переменных, а по завершении освобождает это пространство обратно.
Казалось бы, все просто, но – и это очень жирно.
Но — у нас есть несколько проблем:
- функции вызывают внутри другие функции, которым также нужен стек
- иногда функции вызывают другие функции не путем их прямого упоминания, а по указателю на функцию
- В принципе возможно (хотя этого следует избегать любой ценой) рекурсивно вызывать функции, когда A вызывает B, B вызывает C, а C внутри себя снова вызывает A.
- в любой момент может произойти прерывание, обработчиком которого является та же функция, которая хочет свой кусок стека
- если у вас есть иерархия прерываний, внутри прерывания может произойти другое прерывание!
Все остальное, увы, в общем случае удалить нельзя (хотя в частности могут быть нюансы: например, все ваши прерывания могут иметь одинаковый приоритет по задумке, например, как в ОС RIOT, и вложенных прерываний не будет ).
А теперь представьте себе картину маслом:
- функция A, съевшая 100 байт в стеке, вызывает функцию B, которой нужно 50 байт
- на момент выполнения B сам A явно еще не завершился, поэтому его 100 байт не освобождаются, поэтому в стеке у нас уже есть 150 байт
- функция B вызывает функцию C, и делает это с помощью указателя, который, в зависимости от логики программы, может указывать на полдюжины различных функций, занимающих от 5 до 50 байт стека
- Во время выполнения C происходит прерывание с тяжелым обработчиком, который работает относительно долго и потребляет 20 байт стека.
- Во время обработки прерывания возникает другое прерывание с более высоким приоритетом, обработчик которого требует 10 байт стека.
Причем для одного из них потребление стека не является константой, потому что в разных проходах это может быть просто разная функция, и чтобы понять возможность или невозможность перекрытия прерываний, нужно хотя бы знать, есть ли у вас прерывания с разными приоритеты вообще и, самое большее, понять, могут ли они перекрывать друг друга.
Очевидно, что для любого автоматического статического анализатора кода эта задача крайне близка к невыполнимой и может быть решена лишь в грубом приближении к верхней границе:
- суммировать стеки всех обработчиков прерываний
- суммировать стеки функций, выполняемых в одной ветке кода
- попытаться найти все указатели на функции и их вызовы и принять в качестве размера стека максимальный размер стека среди функций, на которые указывают эти указатели
Поэтому в целом мы можем просто сказать: эта проблема не решается автоматически .
Ручное решение, выполняемое человеком, знающим логику программы, требует обработки довольно большого количества чисел.
Тем не менее статическая оценка размера стека может быть очень полезна при оптимизации ПО — хотя бы для банальной цели понять, кто сколько ест, и не слишком ли это много.
Для этой цели в наборе инструментов GNU/gcc есть два чрезвычайно полезных инструмента:
- -fstack-флаг использования
- утилита cflow
c, компилятор создаст файл %filename%.
su, внутри которого будет простой и понятный текст. Возьмем, к примеру, target.su для эта гигантская портянка :
Теги: #Программирование микроконтроллеров #Производство и разработка электроники #микроконтроллеры #stm32 #Электроника для начинающих #cortex #cortex-m3target.c:159:13:save_settings
-
Компьютерные Сети: Развитие Технологий
19 Oct, 24 -
Раннее Прототипирование Мобильных Приложений
19 Oct, 24 -
Бинокулярное Зрение И Стереопсис
19 Oct, 24