【问题标题】:How to properly use memory pools C++11-style?如何正确使用 C++11 风格的内存池?
【发布时间】:2020-06-15 06:03:56
【问题描述】:

我正在尝试设计一个简单的嵌入式应用程序的内部机制。数据块到达网络,需要传送到由寻址机制确定的组件。多个组件可以订阅同一个地址。我想设计一个架构,其中传入的块被封装到从内存池分配的包装器对象中。只要需要,每个组件都可以保留包装器(以及其中的数据),并且在所有组件释放它时应该将其释放。那时它会返回到池中并再次准备好分配。池耗尽不是问题。

我打算使用满足分配器的this内存池实现。对于包装器对象的自动销毁,我计划使用std::shared_ptr,所以当所有组件释放包装器时,它会自动销毁并将使用的内存返回到池中。

我没有看到这两个概念如何结合在一起。如果我直接从池中分配内存(通过调用allocate()),它会给我一个指向数据块的指针,这很好,但是如何自动调用deallocate()?或者我是否需要为我的包装对象使用另一个容器,例如std::list,并将其传递给内存池分配器?

【问题讨论】:

    标签: c++ c++11 memory-management smart-pointers memory-pool


    【解决方案1】:

    您可以将std::shared_ptr 与使用std::allocate_shared 的自定义分配器一起使用。无论如何,这可能是您想要的,因为我假设您也希望使用池分配器分配控制块(即引用计数)。

    使用std::allocate_shared 构造对象时,分配器的副本存储在shared_ptr 内,因此在销毁时将调用正确的deallocate()。

    请注意,您也可以使用自定义删除器创建 std::shared_ptr,例如:

    auto allocator = getAllocator<Foo>();
    auto ptr = std::shared_ptr<Foo>(new(allocator.allocate()) Foo,
      [&allocator](auto * ptr) { allocator.deallocate(ptr); });
    

    但是,正如我所提到的,这可能不是您想要的,因为不会使用分配器对象为引用计数分配空间。

    顺便说一句,如果你还在“货比三家”,这里有另一个我非常喜欢的内存池实现:foonathan::memory。它提供了自己的allocate_shared。

    【讨论】:

    • 感谢您的回答。关于这一点有一点:内存池中的插槽具有固定大小,必须在编译时知道。我该如何计算?我知道我要分配的对象的大小,分配器也一样(因为复制需要),但是控制块呢?
    • 好问题和我喜欢 foonathan::memory 库的一件事,因为它有一堆帮助功能来帮助解决这些问题。我粗略查看了shared_prt 的API,但看不到任何东西可以让您弄清楚控制块的大小...
    猜你喜欢
    • 1970-01-01
    • 2013-04-29
    • 2014-10-20
    • 2012-01-12
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多