【问题标题】:Globaly replace all new operators全球更换所有新运营商
【发布时间】:2019-08-20 21:13:20
【问题描述】:

我在(嵌入式)C++ 应用程序中使用 RTOS。由于我正在处理嵌入式目标,因此我尝试将堆分配保持在最低限度。但是在某些时候,像向量这样的 STL 类会非常方便。

因为我使用的是 RTOS,所以我必须确保 new/malloc() 调用是线程安全的。幸运的是,我的 RTOS (FreeRTOS) 提供了它自己的(线程安全的)malloc() 例程。我只需要使用它们。

到目前为止,我实现了以下新/删除对并将其链接到二进制文件中。

void * operator new(size_t n) noexcept(false);


void operator delete(void * p) noexcept(true);


void operator delete(void * p, size_t n) noexcept(true);

但是看着这个

https://en.cppreference.com/w/cpp/memory/new/operator_new

向我展示了十几个新的重载(以及删除的重载)。 是否所有新重载或删除重载都默认替换为我的替换,或者我缺少运算符重载?

【问题讨论】:

  • 每个分配东西的 STL 类都提供一个模板参数来指定使用的分配器:template< class T, class Allocator = std::allocator<T> > class vector;
  • 您为什么认为标准分配函数不是线程安全的?
  • 您需要替换程序使用的运算符new(以及相应的运算符delete)的所有重载。您可能会很幸运,但是对于一个运算符 new 的重载默认调用另一个运算符并没有特别的保证。在担心线程安全的分配器/释放器之前,我会认真地看看系统是否可以设计为避免分配和动态释放(例如在启动期间分配,在启动线程之前分配,并在所有启动的线程完成后释放)——即使有线程安全,动态分配和释放也会产生不确定性
  • 通常,在嵌入式系统中,operator new 被定义为只是对 malloc 的调用(例如,在 Arduino 中,newnew[] 都是这样定义的,这反过来又使得使用new[] 分配和使用delete 错误地解除分配安全但不可移植)。您应该实施您的通话之前检查发生了什么。
  • 不幸的是还有另一个问题。如果我尝试使用默认的 new 运算符分配大量数据,则会引发硬错误。这实际上是我更换新操作员的主要意图。是的,在我的嵌入式系统上 new 只是对 malloc 的调用,它不是线程安全的。所以基本上你是说我不能确定特定的 STL 类实际使用的是哪个新运算符? Allocator 类型始终设置为 std::allocator

标签: c++ new-operator


【解决方案1】:

许多operator newoperator delete 重载的标准库的默认行为是转发到operator newoperator delete 的“基本”版本。

“基本”运算符是:

void* operator new (std::size_t count);
void* operator new (std::size_t count, std::align_val_t alignment); // C++17 only
void operator delete(void* ptr) noexcept;
void operator delete(void* ptr, std::align_val_t alignment) noexcept; // C++17 only

假设您有一个标准库实现,该实现实现了 C++ 标准中定义的默认行为¹,上述运算符是您唯一需要替换的运算符。

默认行为最初是在 C++11 标准中定义的,因此您的标准库实现必须至少支持这一点。

[1]:请参阅 C++ 标准中标题为“存储分配和释放 [new.delete]”的部分。

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 2015-07-22
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2017-03-22
    • 2017-02-12
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多