【问题标题】:How can I overload the new operator for multiple heaps?如何为多个堆重载 new 运算符?
【发布时间】:2016-07-26 18:45:46
【问题描述】:

在具有两个独立 RAM 内存区域的嵌入式系统中,我有两个不同的堆(一个是来自 FreeRTOS 的自定义实现,位于较低的内存区域,另一个是 GCC 在较高的内存区域生成的堆),我想以便能够选择新使用的堆。

【问题讨论】:

    标签: c++ operator-overloading


    【解决方案1】:

    您可以提供一个operator new 重载,它接受第二个参数,告诉它从哪个内存区域分配内存。您可以将参数放在operator new 的括号中,放在新表达式中的类型之前。这通常用于 new 将对象放入已分配的存储空间(因为这是标准库提供的重载),但任何东西都可以在那里传递,并将传递给 operator new

    enum MemoryArea {
        LOWER,
        UPPER
    };
    
    void* operator new(std::size_t sz, MemoryArea seg) {
        if (seg == LOWER) {
            return allocateMemoryInLowerMemoryArea(sz);
        } else {
            return allocateMemoryInUpperMemoryArea(sz);
        }
    }
    
    void operator delete(void* p) {
        if (pointerIsInLowerMemoryArea(p)) {
            freeMemoryFromLowerMemoryArea(p);
        } else {
            freeMemoryFromUpperMemoryArea(p);
        }
    }
    
    int main() {
        Foo* p = new (LOWER) Foo;
        Foo* b = new (UPPER) Foo;
        delete p;
        delete b;
    }
    

    【讨论】:

    • 这不是新的展示位置。 Placement new 就地实例化一个对象并且不分配内存。
    • @CaptainObvlious 这与placement new 的语法相同,并且使用相同的机制,但我想你是对的。我会重新措辞。
    • “语法相同”但语义不同,更重要的是。
    • 看起来标准确实将其称为placement new-expression,而不管operator new 重载实际上对参数做了什么。见§[expr.new]/13。
    • 标准将 placement new-expression 定义为具有 new-placement 子句的任何 new-expression假如。 new-placement 子句是new-expression 中类型名称之前的括号表达式列表。这可能仍然不应该被通俗地称为放置新,但它在技术上是正确的。
    【解决方案2】:

    编辑:请参阅已接受的答案,这是不正确的 - UseUpperMemoryNew 会影响 MyClass 的分配,而不是 MyClass 中函数内的分配。 将其留给学习/后代/ cmets。

    对于较低的内存区域,在全局命名空间中

    #include <new>
    #undef new
    
    void* operator new (std::size_t size) throw (std::bad_alloc) { ... }
    void* operator new (std::size_t size, const std::nothrow_t& nothrow_constant) { ... }
    void* operator new[] (std::size_t size) throw (std::bad_alloc) { ... }
    void* operator new[] (std::size_t size, const std::nothrow_t& nothrow_constant) throw() { ... }
    void operator delete (void* ptr) throw () { ... }
    void operator delete (void* ptr, const std::nothrow_t& nothrow_constant) throw() { ... }
    void operator delete[] (void* ptr) throw () { ... }
    void operator delete[] (void* ptr, const std::nothrow_t& nothrow_constant) throw() { ... }
    

    对于高端内存区域,

    void* new2 (std::size_t size) throw (std::bad_alloc) { ... }
    void* new2 (std::size_t size, const std::nothrow_t& nothrow_constant) { ... }
    void delete2 (void* ptr) throw () { ... }
    void delete2 (void* ptr, const std::nothrow_t& nothrow_constant) throw() { ... }
    
    #define UseUpperMemoryNew \
    void* operator new (std::size_t size) throw (std::bad_alloc) { return new2(size); }\
    void* operator new (std::size_t size, const std::nothrow_t& nothrow_constant) { return new2(size, nothrow_constant); }\
    void* operator new[] (std::size_t size) throw (std::bad_alloc) { return new2(size); }\
    void* operator new[] (std::size_t size, const std::nothrow_t& nothrow_constant) throw() { return new2(size, nothrow_constant); }\
    void operator delete (void* ptr) throw () { delete2(ptr); }\
    void operator delete (void* ptr, const std::nothrow_t& nothrow_constant) throw() { delete2(ptr, nothrow_constant); }\
    void operator delete[] (void* ptr) throw () { delete2(ptr); }\
    void operator delete[] (void* ptr, const std::nothrow_t& nothrow_constant) throw() { delete2(ptr, nothrow_constant); }
    

    那么,lower memory 是默认的,upper memory 可以在类级别选择:

    class MyClass
    {
    public:
        UseUpperMemoryArea
        void someFunction(); // new operator use in this function uses upper memory area
    };
    

    我发现你不能在全局命名空间之外重新定义 new - 类级重载是这里唯一的选择。

    【讨论】:

    • 仅供参考,throw(...) 异常规范是 deprecated
    • 这不是特定于类的operator new 重载的工作方式。您的UseUpperMemoryNew 重载不会用于MyClass,它们将用于分配新的MyClass 对象。
    • 如果你要写一篇自我回复的帖子,你需要做得比这更好。
    • 对我自己的问题发布一个不正确、不被接受的答案揭示了它的缺陷,改进了我的代码,并教会了我一些新东西。我认为这做得很好。
    • 将其移至问题正文中的“附录”可能是一个想法。
    猜你喜欢
    • 2011-07-21
    • 1970-01-01
    • 2012-10-18
    • 2020-10-13
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多