我想利用 boost::fast_pool_allocator 的以下广告功能(请参阅 the Boost documentation for Boost Pool ):



(有关此引用,请参阅 here。)

关键短语是 将它们放入遗忘 中。我不希望在这些对象上调用析构函数。

(原因是我有数百万个小对象,它们在堆上形成了一个极其复杂的所有权网络,当单个最父对象离开堆栈时,我的程序需要大约 20 分钟才能调用所有析构函数。我不需要调用这些析构函数,因为没有所需的副作用,并且所有内存都包含在 boost::pool 中。)

不幸的是,尽管有上述文档的 promise ,以及 boost::pool 概念的 promise ,我还是找不到一种方法来防止调用托管对象的析构函数。

问题很容易在一个小示例程序中隔离:

class Obj
{
public:
    ~Obj()
    {
        // Placing a breakpoint here indicates that this is *always* reached
        // (except for the crash scenario discussed below)
        int m = 0;
    }
};

typedef std::map<int, Obj, std::less<int>,
                 boost::fast_pool_allocator<std::pair<int const, Obj>>>
        fast_int_to_int_map;

class Foo
{
public:
    ~Foo()
    {
        // When the following line is uncommented, the program CRASHES
        // when the destructor is exited - because the Obj destructors
        // are called on the invalid Obj ghost instances

        //boost::singleton_pool<boost::fast_pool_allocator_tag,
        //                  sizeof(std::pair<int const, Obj>)>::purge_memory();
    }

    fast_int_to_int_map mmap;
};

void mfoo()
{
    // When this function exits, the Foo instance goes off the stack
    // and its destructor is called, in turn calling the destructors
    // of the Obj instances - this is NOT desired!

    Foo foo;
    foo.mmap[0] = Obj();
    foo.mmap[1] = Obj();
}

int main()
{
    mfoo();

    // The following line deallocates the memory of the pool just fine -
    // but does nothing to prevent the destructors of the Obj instances
    // from being called

    boost::singleton_pool<boost::fast_pool_allocator_tag,
                          sizeof(std::pair<int const, Obj>)>::purge_memory();
}

正如代码注释中所指出的,由 Obj 管理的 boost::pool 实例的析构函数总是被调用。

我该怎么做才能使 Boost Pool 文档 drop them off into oblivion 中的有希望的报价成为现实?

最佳答案

您将自定义分配器传递到您的 std::map 类中。因此,此分配器将用于 std::map 内部的所有内容:用于所有 Obj 数据以及 std::map 二叉树的节点。结果,如果您在 purge_memory() 的析构函数中调用 Foo ,那么所有这些内存都将变得无效,并且会在 std::map 析构函数中崩溃。

您认为自定义分配器负责对象的解除分配的假设是不正确的:释放所有对象是 std::map 的任务。因此,无论您是通过自定义分配器还是使用默认分配器,都会调用 ~Obj()

对于您的问题,我没有看到任何优雅的解决方案。但这种方法应该有效:

  • 使用 placement new 从池的内存中创建 Foo 对象,
  • 像往常一样使用这个 Foo 对象,
  • 调用 purge_memory() 从池中释放所有内存。不会调用析构函数 ~Obj~std::map
  • 关于c++ - 如何防止在 boost::fast_pool_allocator 管理的对象上调用析构函数?,我们在Stack Overflow上找到一个类似的问题:https://stackoverflow.com/questions/22942255/

    10-11 22:47
    查看更多