Голый металл без глобального оператора new

Рассмотрим программное обеспечение для обеспечения безопасности, в котором динамическое распределение вообще запрещено, а исключения запрещены. Динамическое размещение допускается только в том случае, если класс простоты определяет оператор 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 глобально совсем?

5

Решение

Если вы используете GCC и GNU LD, то я думаю, что вы можете просто добавить --wrap=malloc на ваши флаги компоновщика. Как глобальный ::new использования malloc() внутренне все звонки malloc() в вашем приложении будет заменено на __wrap_malloc(), Если эта функция не определена, то соединение не будет выполнено.

Еще один, возможно, более простой вариант, это добавить ASSERT(DEFINED(malloc) == 0, "Dynamic allocation used!"); на ваш скрипт компоновщика. Это будет утверждать, что malloc() не определено.

Ни один из этих вариантов не защитит вас от переопределения глобального ::new использовать какую-то другую форму глобального распределения. Вы можете сделать то же самое для глобального символа ::new в скрипте компоновщика, но его имя искажено (здесь _Znwj), так что это будет немного странно …

4

Другие решения

Независимо от того, какой язык программирования вы используете:

На любой звуковой системе с голым металлом вы просто удаляете .heap сегмент от сценария компоновщика полностью. Любой код, основанный на динамическом размещении, не сможет установить связь. И вам не придется выделять ОЗУ для сегмента, который вы все равно не собираетесь использовать.

3

Есть две вещи, которые я хочу подчеркнуть:

  1. Включение заголовков исключений в их определения не должно беспокоить вас, если исключения не попадают в ваш код.
  2. Когда вы отключаете исключения, вы не можете использовать их в своем коде (компиляция не удастся, если вы это сделаете). Тем не менее, он не удаляет использование исключений из стандартной библиотеки. Стандартная библиотека может содержать предварительно скомпилированные версии шаблонных классов, такие как std::string (Т.е. std::basic_string<char, ...>) или же std::streambuf (Т.е. std::basic_streambuf<char, ...>), и когда вы используете его в своем коде, компилятор не пытается создавать экземпляры шаблонов, он просто использует предварительно скомпилированную версию с исключениями.

Чтобы иметь намного лучший контроль над вашим кодом, я настоятельно рекомендую вообще исключить стандартную библиотеку, используя -nostdlib опция компиляции с компилятором G ++. Это не помешает вам использовать различные классы шаблонов, такие как std::array из STL он просто исключит всю библиотеку C ++ и время выполнения для вас.

Я также рекомендую прочитать Практическое руководство по Bare Metal C ++. Это может дать немного более глубокое понимание внутренних компонентов C ++.

2
По вопросам рекламы [email protected]