Перейти к содержанию
    

Выбор размера кучи и стека.

Форумчане, поделитесь опытом, как вы определяете в своих проектам размер стека и кучи?

какие факторы?

от вольного как то не хочется?

может есть какие то моменты диагностики когда видно, что объема стека или кучи не хватает?

Поделиться сообщением


Ссылка на сообщение
Поделиться на другие сайты

По-моему, подобная тема уже была.

Если совсем уж абстратно, безотносительно потребностей проекта - то вообще пофик, от вольного, от балды. 
Вообще, нужно уточнить, о чем конкретно речь. Если о работе с RTOS, то такая тема тут уже была - там было сказано, что есть некоторые правила по размерам стека задачи, а так же описаны средства диагностики стека. В мануале на FreeRTOS это всё написано.

Если же без RTOS, а в общем и целом, то стек - это динамическая штука, которая изменяется в зависимости от глубины вложенности функций и прерываний и размеров хранящихся локально в них переменных. А куча - это то пространство, которое выделяется функционалом работы с динамической памятью - malloc/free или new/delete. Средств диагностики в общем случае не имеют.  

Поделиться сообщением


Ссылка на сообщение
Поделиться на другие сайты

В 17.02.2024 в 17:15, BALDA сказал:

какие факторы?

Размер вызовов известен, могут еще параметры передаваться, глубину вызовов можно прикинуть и примерно посчитать.

 

В 17.02.2024 в 17:15, BALDA сказал:

может есть какие то моменты диагностики когда видно, что объема стека или кучи не хватает?

При запуске программы забиваете стек например 0xАА - через некоторое время останавливаете отладку и наблюдаете до куда дотянулось.

Поделиться сообщением


Ссылка на сообщение
Поделиться на другие сайты

2 часа назад, BALDA сказал:

Форумчане, поделитесь опытом, как вы определяете в своих проектам размер стека и кучи?

Размер кучи определяю весьма надёжным методом: #define HeapSize 0   :wink:

2 часа назад, BALDA сказал:

может есть какие то моменты диагностики когда видно, что объема кучи не хватает?

Ни разу не сталкивался с такой проблемой.  :wink:

Поделиться сообщением


Ссылка на сообщение
Поделиться на другие сайты

В 17.02.2024 в 15:51, HardEgor сказал:

Размер вызовов известен, могут еще параметры передаваться, глубину вызовов можно прикинуть и примерно посчитать.

 

При запуске программы забиваете стек например 0xАА - через некоторое время останавливаете отладку и наблюдаете до куда дотянулось.

Интересная мысль...

Поделиться сообщением


Ссылка на сообщение
Поделиться на другие сайты

сходу нужно посмотреть : сколько параметров вы передаете в функцию. нет ли функций у которых много локальных переменных или даже массивов. тут же посмотреть с пристрастием. лучше объявить static чтобы не пихать в стек.

а так, если проект небольшой, то под стек 0x400, как по умолчанию. если сложная машина то 0x800.  

а куча уж какая получится.

Поделиться сообщением


Ссылка на сообщение
Поделиться на другие сайты

Размер кучи опеределяется до первой ошибки выделения.

Размер стека предварительно из отчёта по глубине вызовов функций.

В железе - запонением стека константой.

Можно при входе в функции проверять, но это замедляет.

Можно MMU настроить, можно стек расположить по разному.

В общем методов много - выбирается из реальной обстановки

Поделиться сообщением


Ссылка на сообщение
Поделиться на другие сайты

Еще можно так (только для диагностики): стек - по минимальному адресу в указателе стека MSP (это значение сохранять в глобальную static-переменную каждый раз при входе в любую функцию или прерывание. (стек идет сверху вниз, поэтому значение адреса уменьшаются). Куча - аналогично, по максимальному значению адреса, получаемого указателем при динамическом выделении памяти. Если эти адреса пересеклись - всё, хана котёнку, данные повреждены, оперативки выбранного МК недостаточно для всех хотелок.

Поделиться сообщением


Ссылка на сообщение
Поделиться на другие сайты

14 минут назад, EdgeAligned сказал:

Еще можно так (только для диагностики): стек - по минимальному адресу в указателе стека MSP (это значение сохранять в глобальную static-переменную каждый раз при входе в любую функцию или прерывание.

Это не поможет при вызове чужих (библиотечных) функций. А тот же printf() ох как много стека может откушать. Да и компилятор может своих функций нагенерить.

Это во-первых, во-вторых: В случае с РТОС и отдельными стеками для каждой задачи, сохранять придётся не "в глобальную static-переменную", а в область данных текущей задачи.

Поделиться сообщением


Ссылка на сообщение
Поделиться на другие сайты

С кучей все понятно - если используете (или вызываемые функции используют) динамическое выделение памяти (всякие malloc, calloc, realloc в си) то надо считать вручную где и сколько учитывая вложенность вызовов функций. Или при отладке когда там они вернут ошибку невозможности выделения блока памяти.

Со стеком - ошибки от его переполнения ловить сложнее. Нескольких килобайт обычно хватает, если в своих функциях в стеке не выделять массивы и большие структуры. А так если бездумно и на ПК можно поймать в рекурсии переполнение стека.

Признаком переполнения стека у меня было "самопроизвольное" (я так сначала посчитал) изменение значений глобальных переменных и структур

Изменено пользователем kochevkv

Поделиться сообщением


Ссылка на сообщение
Поделиться на другие сайты

On 2/17/2024 at 1:15 PM, BALDA said:

Форумчане, поделитесь опытом, как вы определяете в своих проектам размер стека и кучи?

Quote

«С опытом приходит стандартный, научный подход к вычислению правильного размера стека: взять случайное число и надеяться на лучшее»
— Jack Ganssle, «The Art of Designing Embedded Systems»

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

Куча начинается сразу после глобальных переменны и растет в сторону стека.

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


image.png.42127b2892e1a1489ef1fe054fa8b48e.png

Поделиться сообщением


Ссылка на сообщение
Поделиться на другие сайты

3 часа назад, dimka76 сказал:

Как правила, стек начинается со старшего адреса ОЗУ и растет навстречу глобальным переменным.

Это где такие правила утверждены и кем?

3 часа назад, dimka76 сказал:

Куча начинается сразу после глобальных переменны и растет в сторону стека.

Получается, вам размеры стека и кучи указывать вообще нет никакой необходимости.
Они сами займут весь доступный объем в процессе работы вашей программы.
image.png.42127b2892e1a1489ef1fe054fa8b48e.png

Глупость. Это называется: Разложить себе самому грабли на ровном месте. Когда переполнения стека начнут портить данные в куче. И поиски такой проблемы могут быть весьма длительными.

Любая ошибка должна проявляться как можно сильнее. Чтобы быстро быть обнаруженной. А не заметаться под ковёр. А значит самое разумное - расположить стек в самом начале ОЗУ. Чтобы при переполнении стека шло обращение за пределы ОЗУ и вызывало срабатывание защиты MPU или MMU (если таковой блок имеется).

Поделиться сообщением


Ссылка на сообщение
Поделиться на другие сайты

Quote

 А значит самое разумное - расположить стек в самом начале ОЗУ

Наверное тут уже - сильно очень зависит что за архитектура при делах... 
Но мысль интересная.

ИМХО чтоб с уверенностью - ставить какие то маркеры в RAM и периодически контролировать их. И принимать меры по надобности.
 

Quote

Это где такие правила утверждены и кем?

На тех же AVR если пойнтер не трогать, он по умолчанию грузится в RAMEND....
А в начале адресного пространства - регистры...

Тема, конечно, про ARM, так что уж извините если не к месту.

Изменено пользователем girts

Поделиться сообщением


Ссылка на сообщение
Поделиться на другие сайты

On 4/4/2024 at 8:04 PM, girts said:

На тех же AVR если пойнтер не трогать, 

Тут скорее GCC.
GCC для ARM так же распределяет.
Только отличие в указателе стека. Адрес начала стека надо самому в регистр заносить.
И тут уж можно произвольно указать. Но если не пользоваться всякими ухищрениями, то

обычно вершину ОЗУ и указывают.

Поделиться сообщением


Ссылка на сообщение
Поделиться на другие сайты

On 2/17/2024 at 3:51 PM, HardEgor said:

При запуске программы забиваете стек например 0xАА - через некоторое время останавливаете отладку и наблюдаете до куда дотянулось.

Приём называется "stack painting" (окраска стека). Анализировать % использования стека можно не только в отладчике, но и программно. Бывает полезно при длительном тестовом прогоне оборудования.

Поделиться сообщением


Ссылка на сообщение
Поделиться на другие сайты

Присоединяйтесь к обсуждению

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

Гость
Ответить в этой теме...

×   Вставлено с форматированием.   Вставить как обычный текст

  Разрешено использовать не более 75 эмодзи.

×   Ваша ссылка была автоматически встроена.   Отображать как обычную ссылку

×   Ваш предыдущий контент был восстановлен.   Очистить редактор

×   Вы не можете вставлять изображения напрямую. Загружайте или вставляйте изображения по ссылке.

×
×
  • Создать...