Я хотел бы знать, сколько оперативной памяти я использую в своем проекте, насколько я могу судить, нет никакого способа фактически решить это (кроме как пройти и вычислить это непосредственно). Я попал на стадию в довольно большом проекте, где я определил, что у меня заканчивается ОЗУ.
Я решил это, потому что я могу добавить раздел, а затем все адские разрывы где-то еще в моем коде без видимой причины. Если я #ifndef
что-то еще, это работает снова. В новом коде нет ничего плохого
Некоторое время я подозревал, что получаю конец доступной оперативной памяти. Я не думаю, что я использую слишком много стека (хотя это возможно), каков наилучший способ определить, сколько ОЗУ я фактически использую?
Проходя и пытаясь решить это, у меня возникают проблемы, когда я получаю перечисления и структуры; сколько памяти они стоят?
Первое редактирование: ТАКЖЕ, с самого начала я так много редактировал свой эскиз, это не фактические результаты, которые я изначально получил, а то, что я получаю сейчас.
text data bss dec hex filename
17554 844 449 18847 499f HA15_20140317w.cpp.elf
16316 694 409 17419 440b HA15_20140317w.cpp.elf
17346 790 426 18562 4882 HA15_20140317w.cpp.elf
Первая строка (с текстом 17554) не работала, после большого редактирования вторая строка (с текстом 16316) работает как надо.
редактировать: в третьей строке все работает, последовательное чтение, мои новые функции и т. д. Я по существу удалил некоторые глобальные переменные и дублировал код. Я упоминаю об этом, потому что (как и предполагалось) речь идет не об этом коде, а об использовании оперативной памяти. Что возвращает меня к первоначальному вопросу: «Как лучше измерить это?» Я все еще проверяю некоторые ответы, спасибо.
Как я на самом деле интерпретировать вышеупомянутую информацию?
Пока что мое понимание таково:
`TEXT` is program instruction memory
`DATA` is variables (unitialised?) in program memory
`BSS` is variables occupying RAM
поскольку BSS значительно меньше 1024 байта, почему второй работает, а первый нет? Если это так, DATA+BSS
то оба занимают более 1024.
повторное редактирование: я отредактировал вопрос, включив в него код, но теперь я удалил его, потому что это действительно не имело никакого отношения к проблеме (кроме, возможно, плохой практики кодирования, объявления переменных и тому подобного). Вы можете просмотреть код, просматривая изменения, если вы действительно хотите его увидеть. Я хотел вернуться к рассматриваемому вопросу, который был более основан на: как измерить использование оперативной памяти.
String
тип в своих программах? Известно, что это часто выполняет динамическое выделение и освобождение памяти, что может привести к фрагментации кучи до такой степени, что у вас может не остаться памяти.String
s из-за накладных расходов. Я счастлив работать с массивами символов, тем не менее, я почти всегда определяю все свои массивы символов с фиксированным размером (на данный момент у меня есть ОДИН байтовый массив, который не только потому, что я изменяю длину содержимого для разных перекомпиляций.Ответы:
Вы можете использовать функции AVRGCC: Мониторинг использования стека
Функция была предназначена для проверки использования стека, но она сообщает о фактической оперативной памяти, которая никогда не использовалась (во время выполнения). Это делается путем «раскрашивания» (заполнения) ОЗУ известным значением (0xC5), а затем проверки области ОЗУ с подсчетом количества байтов, имеющих прежнее начальное значение.
В отчете будет отображаться ОЗУ, которое не было использовано (минимальное количество свободной ОЗУ), и поэтому вы можете рассчитать максимальное ОЗУ, которое было использовано (Общая ОЗУ - указанная ОЗУ).
Есть две функции:
StackPaint выполняется автоматически во время инициализации и «закрашивает» ОЗУ значением 0xC5 (при необходимости может быть изменено).
StackCount может быть вызван в любой момент для подсчета ОЗУ, которое не было использовано.
Вот пример использования. Не делает много, но предназначено, чтобы показать, как использовать функции.
источник
Основные проблемы, которые могут возникнуть при использовании памяти во время выполнения:
malloc
илиnew
)Обе они на самом деле одинаковы, поскольку AVR SRAM (2K на Arduino) используется для обеих (в дополнение к статическим данным, размер которых никогда не изменяется во время выполнения программы).
Как правило, динамическое выделение памяти редко используется в микроконтроллерах, обычно его используют лишь несколько библиотек (одна из них -
String
класс, который, как вы упомянули, вы не используете, и это хороший момент).Стек и куча можно увидеть на рисунке ниже (любезно предоставлено Adafruit ):
Следовательно, наиболее ожидаемая проблема возникает из-за переполнения стека (т. Е. Когда стек увеличивается в направлении кучи и переполняется в нем, а затем - если куча не использовалась при всех переполнениях в статической зоне данных SRAM. В то время у вас высокий риск:
Чтобы узнать объем памяти, оставшийся между вершиной кучи и вершиной стека (на самом деле, мы можем назвать это дном, если мы представим и кучу, и стек на одном изображении, как показано ниже), вы можно использовать следующую функцию:
В приведенном выше коде
__brkval
указывает на верхнюю часть кучи, но это0
когда куча не используется, и в этом случае мы используем&__heap_start
указатель__heap_start
на первую переменную, которая отмечает дно кучи;&v
Конечно, указывает на вершину стека (это последняя переменная, помещаемая в стек), поэтому формула, приведенная выше, возвращает объем памяти, доступный для стека (или кучи, если вы ее используете) для роста.Вы можете использовать эту функцию в различных местах вашего кода, чтобы попытаться выяснить, где этот размер резко уменьшается.
Конечно, если вы когда-нибудь увидите, что эта функция возвращает отрицательное число, тогда уже слишком поздно: вы уже переполнили стек!
источник
malloc
иnew
единственный способ , которым я могу это сделать? Если так, то у меня нет ничего динамичного. Кроме того, я только что узнал, что в ООН 2K SRAM. Я думал, что это был 1K. Учитывая это, у меня не хватает оперативной памяти! Мне нужно искать в другом месте.calloc
. Но вы можете использовать сторонние библиотеки, которые используют динамическое размещение, не зная об этом (вам необходимо проверить исходный код всех ваших зависимостей, чтобы быть уверенным в этом)Когда вы выясните, как найти сгенерированный файл .elf во временном каталоге, вы можете выполнить приведенную ниже команду, чтобы сбросить использование SRAM, где
project.elf
его следует заменить сгенерированным.elf
файлом. Преимущество этого вывода - возможность проверить, как используется ваша SRAM. Все ли переменные должны быть глобальными, действительно ли они все обязательны?Обратите внимание, что это не показывает использование стека или динамической памяти, как отметил Игнасио Васкес-Абрамс в комментариях ниже.
Кроме того,
avr-objdump -S -j .data project.elf
можно проверить, но ни одна из моих программ не выводит ничего с этим, так что я не могу точно сказать, полезно ли это. Он должен в список «инициализируются (ненулевые) данных».источник
avr-size
. Но это не покажет вам динамическое распределение или использование стека.avr-objdump
иavr-size
вскоре отредактирую свой пост выше. Спасибо за это.Было бы лучше использовать комбинацию ручной оценки и с использованием
sizeof
оператора. Если все ваши объявления статичны, то это должно дать вам точную картину.Если вы используете динамическое распределение, вы можете столкнуться с проблемой, как только начнете освобождать память. Это связано с фрагментацией памяти в куче.
Перечисление занимает столько же места, сколько и
int
. Итак, если у вас есть набор из 10 элементов вenum
объявлении, это будет10*sizeof(int)
. Кроме того, каждая переменная, которая использует перечисление, является простоint
.Для структур было бы легче использовать,
sizeof
чтобы узнать. Структуры занимают (минимальное) пространство, равное сумме его членов. Если компилятор выполняет выравнивание структуры, это может быть больше, однако это вряд ли в случаеavr-gcc
.источник
sizeof
для этой цели. На данный момент у меня уже есть почти 400 байтов (глобально). Теперь я пройду и вычислю перечисления (вручную) и структуры (которых у меня есть несколько - и я буду использоватьsizeof
), и доложу.sizeof
знать размер ваших статических данных, поскольку они распечатываются avrdude IIRC.Существует программа под названием Arduino Builder, которая обеспечивает аккуратную визуализацию количества флэш-памяти, SRAM и EEPROM, которые использует ваша программа.
Конструктор Arduino является частью IDE- решения CodeBlocks Arduino . Его можно использовать как автономную программу или через IDE CodeBlocks Arduino.
К сожалению, Arduino Builder немного стар, но он должен работать для большинства программ и большинства Arduinos, таких как Uno.
источник