STL во встроенной системе с очень ограниченной памятью - PullRequest
10 голосов
/ 08 марта 2012

В настоящее время я работаю над созданием встроенной системы с использованием процессора ARM Cortex M3 с 64 КБ SRAM. В данный момент я ищу способ обеспечить детерминированную производительность с контейнерами STL, который включает в себя гарантию того, что я не смогу закончить нехватку памяти во время выполнения.

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

Я работаю с другими людьми в этом проекте, которые не хотят заниматься необработанным распределением памяти и предпочли бы иметь возможность использовать «хорошо известные» структуры данных (стек, очередь, очередь и т. Д.). Поэтому в настоящее время я рассматриваю возможность создания оболочек вокруг C-массивов для обеспечения этих структур. Это позволило бы статическое выделение памяти, необходимой для поддержки этих контейнеров, и позволило бы другим разработчикам знать размер контейнера, который они создали до запуска, на основе информации о размере кода, предоставленной компилятором. На мой взгляд, это гарантирует, что проблемы с нехваткой памяти не могут возникнуть во время выполнения, и значительно упрощает проектирование системы.

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

Буду признателен за любые комментарии относительно моего предложения по созданию классов вокруг стандартных C-массивов? Кроме того, существует ли более простой способ выделить контейнер STL статического размера, например стек или очередь статического размера, во время компиляции? (Я знаю, что это возможно с вектором, но другие я не уверен)

Примечание: я прочитал другой вопрос ( Embedded C ++ для использования STL или нет ), но автор этого вопроса не уточнил, сколько у них памяти (кроме того, как они были используя процесс ARM7) или, кажется, рассматривает решение, подобное моему.

Второе примечание: я знаю, что для некоторых разработчиков 64 КБ SRAM могут выглядеть как много памяти. На самом деле, я разработал процессоры AVR со значительно меньшим объемом памяти, поэтому я понимаю эту точку зрения. Однако, с моей текущей (возможно, неинформированной) точки зрения, 64 КБ памяти не так много, если говорить о контейнерах STL.

Ответы [ 3 ]

10 голосов
/ 08 марта 2012

Этот вопрос немного запутанный и странный.Во-первых, давайте разберемся с некоторыми заблуждениями.

Вы упоминаете «стек, очередь, deque» по имени.Ну, два из них не контейнеры .stack и queue являются контейнерными адаптерами.Видите, они на самом деле не хранят элементы напрямую;они просто опосредуют интерфейс к ним.stack гарантирует, что вы можете только толкать, выталкивать и получать верхний элемент.queue гарантирует, что вы можете только push-back, pop-front и получить передний элемент (хотя он также позволяет получить задний элемент).

Адаптеры контейнера фактически принимают в качестве одного из своих параметров шаблонафактический тип контейнера для использования.Так что вы можете использовать stack с std::list, если хотите.Я не обязательно предлагал бы это (в зависимости от вашего варианта использования), но вы могли бы .

Контейнерным адаптерам плевать на память;это контейнеры, которые они используют , которые выделяют память.

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

Например, если у вас есть vector, который должен работать в пределах 2 КБ памяти, если он имеет размер 1 КБ и пытается выделить еще 2,5 КБ, распределитель не может просто вернуть 2 КБ.Он может вернуть 2.5KB по запросу или throw std::bad_alloc.Это ваши только два варианта.Распределитель не может сообщить vector, что он может получить больше памяти, чем у него, но не так много, как он хочет.

Аналогично, распределитель должен предоставить new память, только что выделенная память, которую можно скопировать в.Он не должен предоставлять то же место памяти только с большим количеством доступного.Это может вызвать проблемы в некоторых реализациях.

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

Я предлагаю отследить копию EASTL .Он действительно предназначен для такого рода вещей.В репозитории Github, с которым я вас связывал, есть исправления ошибок и т. Д., Но в большинстве случаев он остается тем же.Это неплохой код.Их STL-подобные контейнеры обеспечивают большую часть интерфейса, поэтому они могут быть в основном заменой.Но они предоставляют специальную функциональность для конкретного управления распределением памяти.

0 голосов
/ 27 июня 2019

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

Встроенная библиотека шаблонов (лицензия MIT) https://www.etlcpp.com

0 голосов
/ 04 февраля 2017

Помимо EASTL , вы также можете использовать static_vector от наддува.Он разделяет большую часть API с std::vector и может использоваться с контейнерными адаптерами (очередь, стек).Вместо std::bad_alloc он может вызвать throw_bad_alloc(), поэтому его можно использовать во встроенной среде без исключений.

...