Как заставить компилятор гарантировать, что выделение памяти для локальных переменных не приведет к переполнению оперативной памяти во время выполнения?
После компиляции скетча с помощью Arduino IDE в консоли отображается сообщение, подобное следующему:
Global variables use 1540 bytes (75%) of dynamic memory, leaving 508 bytes for local variables. Maximum is 2048 bytes.
Кроме того, кажется, что если использование глобальных переменных превышает примерно 75% от общего объема динамической памяти, дополнительно отображается следующее сообщение:
Low memory available, stability problems may occur.
Похоже, что при обычном использовании IDE компилятор не гарантирует, что выделение памяти локальным переменным не вызовет переполнения ОЗУ во время выполнения программы. Вместо этого он просто отображает предупреждающее сообщение, когда для локальных переменных остается мало оперативной памяти.
Это может привести к сбоям в работе программы во время выполнения, если локальные переменные занимают больше места, чем оставшаяся оперативная память.
Как заставить компилятор определить, приведет ли выделение памяти к локальным переменным к переполнению ОЗУ во время выполнения или нет, и предупредить пользователя во время компиляции только в этих конкретных случаях?
@Ramanewbie, 👍2
Обсуждение1 ответ
Лучший ответ:
Вы описываете "профилирование памяти" и обычно не является функцией C или C++. Это чаще встречается в языках более высокого уровня, таких как Java, но C считается языком гораздо более низкого уровня.
Обычно такое профилирование выполняется во время выполнения с использованием внешних инструментов, таких как valgrind
и massif
.
На самом деле компилятор не может понять, что будет делать ваша программа, если он использует внешние данные и входные данные для управления своей работой. Любые такие тесты во время компиляции были бы в значительной степени бессмысленными, так как любые, прошедшие тестирование, могут по-прежнему вызывать проблемы во время выполнения в зависимости от того, что еще может происходить в то же время или даже от того, что могло произойти в прошлом (см. фрагментация кучи).
- Глобальные переменные занимают много места в динамической памяти.
- Есть ли константа для максимального значения Unsigned Long в компиляторе Arduino?
- Как уменьшить использование памяти в коде?
- Выделение памяти указателя в функции
- Запрос на помощь в сжатии кода и сохранении памяти
- Считывание байтов из массива PROGMEM
- Можете ли вы помочь мне сократить мой код?
- Включает ли скомпилированный бинарный файл скетча неиспользуемые функции из библиотеки?
компилятор ничего не знает о логике программы, @jsotola
Как вы ожидаете, что компилятор угадает, что может произойти в вашей программе, которая полагается на внешние стимулы для управления своей работой?, @Majenko
@Majenko В общем, нет; однако во многих случаях для компилятора должно быть очевидно, что локальные переменные обязательно вызовут переполнение ОЗУ во время выполнения. Я ожидаю, что компилятор, по крайней мере, сможет выдать ошибку компиляции в этих очевидных случаях (случаях, которые не зависят от какого-либо внешнего стимула)., @Ramanewbie
и почему вы спрашиваете это здесь на Arduino SE?, @Juraj
@Juraj Что еще вы предлагаете?, @Ramanewbie
возможно, список рассылки разработчиков GCC, @Juraj
Базовый GCC может иметь возможность проверять во время выполнения, не использует ли стек используемую оперативную память, в зависимости от его версии. Но я понятия не имею, как добавить такую потенциальную опцию в Arduino IDE. Обратите внимание, что это замедляет ваш скетч, потому что эта проверка, скорее всего, выполняется каждый раз, когда увеличивается используемое пространство стека, то есть при вызовах функций/методов или выделении локальных переменных., @the busybee
компилятор может обнаружить ранние проблемы. исчерпание пространства var является поздней проблемой. бывший. во время кодирования вы можете зарезервировать 20 байтов для имени пользователя, но затем появляется _Hubert Blaine Wolfeschlegelsteinhausenbergerdorff Sr._, и ваши хорошо продуманные планы не сбываются., @dandavis
Посмотрите на это так. Если у вас есть 2 КБ ОЗУ и 2 функции, a() и b(), каждая из которых динамически выделяет 1,5 КБ, вы можете быть в порядке. Это зависит. Это определенно неудача, если b() вызывает a(), a() вызывает a() и т. д. Если a() и b() никогда не активны одновременно, это может сработать. Если b() вызывает a() в зависимости от пользовательского ввода во время выполнения, компилятор этого не видит., @6v6gt