Является ли realloc () безопасным во встроенной системе? - PullRequest
9 голосов
/ 25 августа 2011

При разработке программного обеспечения для встроенной системы я много раз использовал функцию realloc(). Теперь мне сказали, что я «не должен использовать realloc() во встроенном» без объяснения причин.

Опасно ли realloc() для встраиваемой системы и почему?

Ответы [ 6 ]

20 голосов
/ 25 августа 2011

Да, все динамическое распределение памяти считается опасным, и оно запрещено для большинства встроенных систем "высокой целостности", таких как промышленные / автомобильные / аэрокосмические / медтехнологические и т. Д. И т. Д. Ответ на ваш вопрос зависит от того, какого родавстроенной системы, которую вы делаете.

Причины, по которым он запрещен для встроенных систем с высокой степенью целостности, связаны не только с потенциальными утечками памяти, но и с множеством опасных неопределенных / неуказанных / подразумеваемых действий, связанных с этими функциями.

РЕДАКТИРОВАТЬ: Я также забыл упомянуть фрагментацию кучи, что является еще одной опасностью.Кроме того, MISRA-C также упоминает «несогласованность данных, исчерпание памяти, недетерминированное поведение» в качестве причин, по которым их не следует использовать.Первые два кажутся довольно субъективными, но недетерминированное поведение определенно является недопустимым в подобных системах.

Ссылки:

  • MISRA-C: 2004 Правило 20.4«Динамическое выделение памяти кучи не должно использоваться.»
  • МЭК 61508 Функциональная безопасность, 61508-3 Приложение B (нормативное) Таблица B1,> SIL1: «Нет динамических объектов», «Нет динамических переменных».
5 голосов
/ 25 августа 2011

Это зависит от конкретной встроенной системы.Динамическое управление памятью в небольшой встроенной системе сложно начать, но realloc не сложнее, чем free и malloc (конечно, это не то, что он делает).В некоторых встроенных системах вы никогда не мечтали бы позвонить malloc.В других встроенных системах вы почти притворяетесь, что это настольный компьютер.

Если у вашей встроенной системы плохой распределитель или мало ОЗУ, то realloc может вызвать проблемы фрагментации.Вот почему вы также избегаете malloc, потому что это вызывает те же проблемы.

Другая причина в том, что некоторые встроенные системы должны иметь высокую надежность, и malloc / realloc может возвращать NULL.В этих ситуациях вся память выделяется статически.

4 голосов
/ 27 августа 2011

Во многих встроенных системах пользовательский менеджер памяти может обеспечить лучшую семантику, чем это доступно в malloc / realloc / free. Например, некоторые приложения могут обойтись простым распределителем меток и выпусков. Держите указатель на начало еще не выделенной памяти, выделяйте объекты, перемещая указатель вверх, и сбрасывайте их, перемещая указатель под ними. Это не сработает, если необходимо отбросить некоторые вещи, оставив после себя другие, выделенные после них, но в ситуациях, когда в этом нет необходимости, распределитель меток и выпусков дешевле, чем любой другой метод выделения. В некоторых случаях, когда распределитель меток и выпусков не достаточно хорош, может быть полезно выделить некоторые вещи из начала кучи и другие вещи из конца кучи; можно освободить вещи, выделенные с одного конца, не влияя на вещи, выделенные с другого.

Еще один подход, который иногда может быть полезен в системах, не использующих многозадачность или совместную многозадачность, - это использование ручек памяти, а не прямых указателей. В типичной системе на основе дескрипторов есть таблица всех выделенных объектов, построенных в верхней части памяти и работающих вниз, а сами объекты размещаются снизу вверх. Каждый выделенный объект в памяти содержит либо ссылку на слот таблицы, которая ссылается на него (если он активен), либо указание на его размер (если он мертв). Запись таблицы для каждого объекта будет содержать размер объекта, а также указатель на объект в памяти. Объекты могут быть распределены путем простого нахождения свободного слота таблицы (легко, поскольку все слоты таблицы имеют фиксированный размер), сохранения адреса слота таблицы объекта в начале свободной памяти, сохранения самого объекта непосредственно за этим и обновления начала свободной памяти, чтобы указать только мимо объекта. Объекты могут быть освобождены путем замены обратной ссылки на указание длины и освобождения объекта в таблице. Если выделение не удастся, переместите все живые объекты, начиная с верхней части памяти, перезаписывая все мертвые объекты и обновляя таблицу объектов, чтобы они указывали на их новые адреса.

Эффективность этого подхода недетерминирована, но фрагментация не является проблемой. Кроме того, в некоторых совместных многозадачных системах может быть возможно выполнять сборку мусора «в фоновом режиме»; при условии, что сборщик мусора может завершить проход за то время, которое требуется для прохода через свободное пространство, можно избежать длительного ожидания. Кроме того, для повышения производительности в среднем случае может использоваться некоторая довольно простая «порождающая» логика за счет производительности в худшем случае.

2 голосов
/ 25 августа 2011
  1. realloc может потерпеть неудачу, как malloc может.Это одна из причин, по которой вам, вероятно, не следует использовать ни одну из них во встроенной системе.

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

  3. Использование reallocбудет очень опасно, потому что он может вернуть новый указатель на вашу память.Это означает:

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

Обновление :Я просто хотел прояснить это.Я не говорю, что realloc хуже, чем реализация realloc с использованием malloc / free.Это было бы так же плохо.Если вы можете сделать один malloc и free без изменения размера, это немного лучше, но все же опасно.

1 голос
/ 27 августа 2011

Проблемы с realloc () во встроенных системах ничем не отличаются от других систем, но последствия могут быть более серьезными в системах, где память более ограничена, а последствия сбоя менее приемлемы.

Одна проблема, не упомянутая до сих пор, состоит в том, что realloc () (и любая другая операция с динамической памятью в этом отношении) является недетерминированной ;то есть время его выполнения является переменным и непредсказуемым.Многие встраиваемые системы также являются системами реального времени , и в таких системах недетерминированное поведение недопустимо.

Другая проблема заключается в безопасности потоков.Проверьте документацию вашей библиотеки, чтобы увидеть, является ли ваша библиотека поточно-ориентированной для динамического распределения памяти.Как правило, если это так, вам потребуется реализовать заглушки мьютекса, чтобы интегрировать их с вашей конкретной библиотекой потоков или ОСРВ.

Не все emebdded системы одинаковы;если ваша встроенная система не работает в режиме реального времени (или рассматриваемый процесс / задача / поток не в реальном времени и не зависит от элементов реального времени), и у вас большой объем неиспользуемой памяти или возможности виртуальной памяти,тогда использование realloc () может быть приемлемым, хотя, возможно, в большинстве случаев и неуместным.

Вместо того, чтобы принимать «общепринятую мудрость» и запрет динамической памяти, вы должны понимать требования к вашей системе и поведениединамические функции памяти и принять соответствующее решение.Тем не менее, если вы создаете код для возможности использования и переносимости для максимально широкого спектра платформ и приложений, то перераспределение, вероятно, является действительно плохой идеей.Например, не скрывайте его в библиотеке.

Обратите внимание, что та же проблема существует с классами контейнеров C ++ STL, которые динамически перераспределяют и копируют данные при увеличении емкости контейнера.

0 голосов
/ 25 августа 2011

Что ж, лучше избегать использования realloc, если это возможно, так как эта операция является дорогостоящей, особенно когда она помещается в цикл: например, если необходимо увеличить объем выделенной памяти и нет промежутка между текущим и следующим выделенным блоком block - эта операция почти равна: malloc + memcopy + free.

...