Рассмотрим программное обеспечение для обеспечения безопасности, в котором динамическое распределение вообще запрещено, а исключения запрещены. Динамическое размещение допускается только в том случае, если класс простоты определяет оператор new
а также delete
, Использование оператора new
для других класс должен вызывать сбой компиляции.
Самый простой способ вызвать сбой компиляции в описанной ситуации — удалить глобальный новый оператор:
void* operator new(std::size_t) = delete;
С одной стороны это вызывает побочные эффекты со стандартной библиотекой. Например, включая <array>
распространяет включение в <new_allocator>
от <stdexcept>
, <new_allocator>
использования ::new
оператор и это приводит к сбою сборки, даже если вы не хотите использовать исключение и выделение памяти. По словам Скот Мейерс <array>
должен быть дружелюбным к голому металлу.
С другой стороны, это приводит к ошибке со встроенным оператором компилятора.
src/main.cpp:91:31: error: deleted definition of 'void* operator new(std::size_t)'
void* operator new(std::size_t) = delete; ^
<built-in>: note: previous declaration of 'void* operator new(std::size_t)'
Есть ли решение, чтобы запретить ::new
и использовать <array>
?
Есть ли решение, чтобы запретить ::new
глобально совсем?
Если вы используете GCC и GNU LD, то я думаю, что вы можете просто добавить --wrap=malloc
на ваши флаги компоновщика. Как глобальный ::new
использования malloc()
внутренне все звонки malloc()
в вашем приложении будет заменено на __wrap_malloc()
, Если эта функция не определена, то соединение не будет выполнено.
Еще один, возможно, более простой вариант, это добавить ASSERT(DEFINED(malloc) == 0, "Dynamic allocation used!");
на ваш скрипт компоновщика. Это будет утверждать, что malloc()
не определено.
Ни один из этих вариантов не защитит вас от переопределения глобального ::new
использовать какую-то другую форму глобального распределения. Вы можете сделать то же самое для глобального символа ::new
в скрипте компоновщика, но его имя искажено (здесь _Znwj
), так что это будет немного странно …
Независимо от того, какой язык программирования вы используете:
На любой звуковой системе с голым металлом вы просто удаляете .heap
сегмент от сценария компоновщика полностью. Любой код, основанный на динамическом размещении, не сможет установить связь. И вам не придется выделять ОЗУ для сегмента, который вы все равно не собираетесь использовать.
Есть две вещи, которые я хочу подчеркнуть:
std::string
(Т.е. std::basic_string<char, ...>
) или же std::streambuf
(Т.е. std::basic_streambuf<char, ...>
), и когда вы используете его в своем коде, компилятор не пытается создавать экземпляры шаблонов, он просто использует предварительно скомпилированную версию с исключениями.Чтобы иметь намного лучший контроль над вашим кодом, я настоятельно рекомендую вообще исключить стандартную библиотеку, используя -nostdlib
опция компиляции с компилятором G ++. Это не помешает вам использовать различные классы шаблонов, такие как std::array
из STL он просто исключит всю библиотеку C ++ и время выполнения для вас.
Я также рекомендую прочитать Практическое руководство по Bare Metal C ++. Это может дать немного более глубокое понимание внутренних компонентов C ++.