【发布时间】:2017-01-02 11:57:25
【问题描述】:
考虑安全软件,其中通常不允许动态分配并且不允许异常。仅当类明确定义运算符new 和delete 时才允许动态分配。对其他类使用运算符new 会导致编译失败。
在所述情况下导致编译失败的最简单方法是删除全局 new 运算符:
void* operator new(std::size_t) = delete;
一方面,这会对标准库产生副作用。例如,包含<array> 会通过<stdexcept> 将包含传播到<new_allocator>。 <new_allocator> 使用 ::new 运算符,即使您不想使用异常和内存分配,这也会导致构建失败。根据 Scoot Meyers 的说法,<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?
【问题讨论】:
-
您是否可以接受稍后在链接时出现的错误?
-
C 有时是有充分理由的。这听起来像是其中之一。 C 不会产生隐藏的开销。
new不是唯一的问题,但惯性也会导致麻烦,例如用于中断处理程序和其他时间关键路径。 -
这将是 C++ 不常用于此类系统的原因之一。事实上,安全关键软件通常需要使用经过验证的库,这实际上将大部分
std::排除在普通嵌入式系统编译器之外。 -
@Olaf 继承对中断处理程序几乎没有性能影响。与静态链接函数相比,调用虚拟函数(无论如何在 ARM 上)的开销为 0-1 个周期。
-
@RussSchultz:我在哪里说过开销会是问题?问题是确定性行为。使用虚函数,您可以轻松调用您从未想过甚至没有想过的函数。说:在典型的嵌入式系统上,额外间接的开销非常重要。例如,对于 STM32F,Flash 可能需要超过 8 或 10 个额外的时钟周期。小“缓存”往往无法捕捉到这种情况;更少,因为它是一种数据访问,也会干扰预取。正如我所写:麻烦
标签: c++ c++11 memory-management embedded bare-metal