Отключить динамическое выделение памяти? - PullRequest
1 голос
/ 15 марта 2019

Я пытаюсь вообще отключить динамическое выделение памяти в приложении с ограниченными ресурсами.Я никогда не использую malloc / free и т. Д. И, насколько я могу судить, не использует ни одну из моих зависимостей.

Я попытался обнулить кучу в файле компоновщика LinkerScript.ld:

_Min_Heap_Size = 0x000;  /* required amount of heap  */

Но это не является гарантией того, что ни одна библиотечная функция не будет пытаться вызвать malloc.

Есть ли способ обеспечить, что динамическое выделение памяти не может занятьПоместить и завершить сборку, если это так?

В этом проекте НЕТ операционной системы (голая, STM32F302R8 ), скомпилированной с arm-none-eabi-gcc.

Ответы [ 2 ]

3 голосов
/ 15 марта 2019

В наиболее распространенном наборе инструментов Cortex-M на основе gcc библиотечные функции предоставляются библиотекой newlib C. Реализация newlib malloc() и друзей выделяет память для кучи с помощью функции _sbrk(), которая должна быть реализована программным обеспечением пользователя.

Если в вашем приложении нет _sbrk(), сборка завершится неудачно. Найдите и удалите.

Возможно, вы также захотите узнать, как узнать , почему на символ ссылаются , или делает сборку неудачной при ссылке на произвольную библиотечную функцию

0 голосов
/ 15 марта 2019

Я пытаюсь вообще отключить динамическое выделение памяти в приложении с ограниченными ресурсами.

Это необычно.Обычно люди ограничивают динамическую память, используемую их (размещенным) приложением (и как это сделать, это другой вопрос, часто для конкретной операционной системы ).Почему вы хотите отключить его полностью ?Как объясняется ниже, весьма вероятно, что динамическая память будет использоваться для внутреннего использования внутри вашей стандартной библиотеки C * Реализация 1014 *.


Внимательно прочитайте стандарт C11 n1570 (или C99).

В основном существует два "режима" или два "диалекта" C: размещенный язык C и автономный язык C.Точная формулировка §4 соответствия стандарта:

Две формы соответствующей реализации являются размещенными и автономными.Соответствующая размещенная реализация должна принимать любую строго соответствующую программу.Соответствующая автономная реализация должна принимать любую строго соответствующую программу, в которой использование функций, указанных в разделе библиотеки (пункт 7), ограничено содержимым стандартных заголовков <float.h>, <iso646.h>, <limits.h>, <stdalign.h>, <stdarg.h>, <stdbool.h>, <stddef.h>, <stdint.h> и <stdnoreturn.h>.

И malloc определены (объявлены в <stdlib.h>) и должны быть доступны для размещено реализаций и обычно не доступно в автономных реализациях (но это зависит от реализации).

Очевидно, вы используете автономную реализацию (так как у вас нет malloc, что стандарттребует от размещенных реализаций).Для этого GCC имеет режим -ffreestanding.Вы должны использовать это.Тогда <stdlib.h> недоступен, и ваш код не может использовать стандарт malloc в этом режиме (если он явно не объявляет malloc).

В размещенной реализации вы обычноможет переопределить ваш malloc (при условии, что он все еще обладает всеми свойствами, требуемыми стандартом).Тогда вы можете использовать что-то вроде this (всегда сбойная, но все еще соответствующая стандарту реализация malloc).

Наконец, если вы используете GNU binutils компоновщик, вы всегда можете потерпеть неудачу в ссылке, если ваши объектные файлы содержат какие-либо внешние ссылки на malloc.Это просто реализовать - добавив какой-то конкретный рецепт или правило - в ваш Makefile (вероятно, используя nm), или если вы используете какой-либо приличный инструмент автоматизации сборки (если вашАвтоматизация сборки не разрешает такую ​​проверку непосредственно перед установкой связи, переключитесь на такую ​​проверку: make, ninja, omake и многие другие.другие ....).

Если вы хотите обнаружить любое использование malloc в время компиляции в среде , вы можете написать свой собственный GCC плагин делает это (я чувствую, что это излишне, но выбор за вами).Или (гораздо более простой на практике) использовать какой-либо сценарий (например, с grep ), обнаруживающий появление слова malloc или calloc в исходном коде C.

Обратите внимание, что в большинстверазмещенные реализации, на практике стандартные функции, такие как fprintf, fopen, printf, fputc (и многие другие), внутренне - хотя бы иногда - используют malloc.Конкретно, если ваша программа (выше размещенной реализации) использует fopen, весьма вероятно, что она косвенно использует malloc, поскольку внутри стандарта FILE обычно есть некоторый выделенный из кучи буфер, который fopen равен malloc -ing (и обычно он получает free -d во время fclose).

Есть ли способ принудительно установить, что динамическое выделение памяти не может быть выполнено, и в этом случае сборка завершится неудачно?

На практике да.Просто добавьте какой-нибудь скрипт в ваш Makefile, делающий такую ​​проверку.Либо используйте grep в ваших исходных файлах, либо используйте nm в ваших объектных файлах.Но если вы используете в своем коде стандартный fopen (из <stdio.h>), он обычно выполняет некоторые malloc для внутреннего использования.

Во многих операционных системах (той, что используется вашим приложением, если таковые имеются), существует способ ограничения кучи памяти во время выполнения.Linux имеет setrlimit (2) с RLIMIT_DATA.

Если вы используете бесплатное программное обеспечение или стандартную библиотеку с открытым исходным кодом C реализацию(в размещенной среде), такой как GNU glibc или musl-libc , вы можете изучить его исходный код и проверить, что fopen использует кучу памяти.

...