STL внутри врезанной системы с очень ограниченной памятью

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

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

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

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

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

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

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

2 ответов


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

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

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

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

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

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

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

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

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


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