没有全球运营商的裸机

时间:2017-01-02 11:57:25

标签: c++ c++11 memory-management embedded bare-metal

考虑安全软件,一般不允许动态分配,不允许例外。仅当class explicity定义operator newdelete时才允许动态分配。对其他类使用运算符new会导致编译失败。

在描述的情况下导致编译失败的最简单方法是删除全局新运算符:

void* operator new(std::size_t) = delete;

一方面,这会导致标准库的副作用。例如,<array>包括<new_allocator><stdexcept>传播到<new_allocator>::new使用<array>运算符,即使您不想使用异常和内存分配,这也会导致构建失败。根据Scoot Meyers 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

是否有任何解决方案可以全局禁止Gemfile

3 个答案:

答案 0 :(得分:4)

如果您使用GCC和GNU LD,那么我认为您只需将--wrap=malloc添加到链接器标志即可。由于全局::new在内部使用malloc(),因此应用程序中对malloc()的所有调用都将替换为__wrap_malloc()。如果此函数未定义,则链接将失败。

另一个可能更简单的选择是将ASSERT(DEFINED(malloc) == 0, "Dynamic allocation used!");添加到链接描述文件中。这将断言malloc()未定义。

这两个选项都不会保护您重新定义全局::new以使用其他形式的全局分配。您可以在链接描述文件中为全局符号::new执行相同的操作,但它的名称会被修改(在此处为_Znwj),所以这会有点奇怪......

答案 1 :(得分:3)

无论您使用何种编程语言:

在任何声音,裸机系统上,您只需完全从链接描述文件中删除.heap段。依赖于动态分配的任何代码都将无法链接。并且您不必为您无法使用的段分配RAM。

答案 2 :(得分:2)

我想强调两件事:

  1. 如果异常无法进入您的代码,则不应将包含与异常相关的标头及其定义包含在内。
  2. 禁用例外时,不能在代码中使用它们(如果这样做,编译将失败)。但是,它不会从标准库中删除异常的使用。标准库可能包含模板类的预编译版本,例如std::string(即std::basic_string<char, ...>)或std::streambuf(即std::basic_streambuf<char, ...>),以及当您在代码,编译器不会尝试实例化模板,它只是重用预编译版本。
  3. 为了更好地控制代码,我强烈建议使用带有G ++编译器的-nostdlib编译选项完全排除标准库。它不会阻止您使用各种模板类,例如来自STL的std::array,它将为您排除整个C ++库和运行时。

    我还建议阅读Practical Guide to Bare Metal C++。它可能会对C ++裸机内部提供更深入的了解。