创建符合 std 的分配器,用于包装用于诊断的任意分配器

Create std-compliant allocator that wraps arbitrary allocator for diagnostics

提问人:Steven 提问时间:11/11/2023 最后编辑:Steven 更新时间:11/11/2023 访问量:53

问:

作为自定义 std 兼容容器的单元测试套件的一部分,我想做一些内存跟踪。最简单的方法是定义一个新的分配器并用它跟踪分配和解除分配,然后调用 malloc 和 free。但是,在某些情况下,我想使用不同的分配器作为子分配器并通过它路由所有分配。除了容器所需的重新绑定之外,这有点工作。它也仅限于 std::allocator,这对于使用其他分配器进行单元测试不是很好。我正在使用 C++/17 来做到这一点。

到目前为止,我有这个工作示例分配器,但基本分配器的类型是固定的 - 它仅适用于 std::allocators。

template <typename T, typename BaseAllocator = std::allocator<T> >
struct TrackingAllocator
{
    typedef T value_type;

    TrackingAllocator() = default;
    TrackingAllocator( const TrackingAllocator& aOther ) noexcept = default;

    template <class U>
    constexpr TrackingAllocator( const TrackingAllocator<U, std::allocator<U>>& ) noexcept {}

    // recognize this is old style; would like to move to new style C++17 rebind
    template <class U>
    struct rebind
    {
        using other = TrackingAllocator<U, std::allocator<U>>;
    };

    BaseAllocator m_allocator;

    T* allocate( std::size_t n )
    {
        // track allocation
        return m_allocator.allocate( n );
    }

    void deallocate( T* p, std::size_t n ) noexcept
    {
        // track deallocation
        m_allocator.deallocate( p, n );
    }
    // allocation logging
};

但是,我需要它与任何类型的分配器一起使用:

std::vector<int, TrackingAllocator< FixedAllocator<int> > > vector_of_ints;

我的目标是能够编写测试,例如:

TrackingAllocator<int> trackingAllocator;
{
    CustomContainer<TrackingAllocator<int>> container ( trackingAllocator );

    // a bunch of allocation-related operations
    EXPECT_EQ( trackingAllocator.allocationCount, the_expected_number );

    container.shrink_to_fit();

    EXPECT_EQ( trackingAllocator.allocationCount, the_expected_number );
}
// container out of scope, free memory in container
EXPECT_EQ( trackingAllocator.allocationCount, 0 );

但我正在为两个问题而苦苦挣扎:

  1. 如何让现代重新绑定工作,因为 C++ 中已弃用 rebind17
  2. 子分配器重新绑定到新的 U 型。

我遇到的问题是我无法在此调用中从反弹分配器返回正确的 T*:

    T* allocate( std::size_t n )
    {
        // m_allocator's T and the rebound Tracking
        // allocator's T are not related.
        return m_allocator.allocate( n );
    }

有什么办法可以解决这个问题吗?

C++ 模板 分配器

评论

0赞 StoryTeller - Unslander Monica 11/11/2023
你看过std::allocator_traits吗?据推测,它应该足以让你的分配器很好地使用它。
1赞 StoryTeller - Unslander Monica 11/11/2023
如果我收集正确,您基本上只需要始终是 to 的反弹版本,这将使您的模板与 .m_allocatorBaseAllocatorTTrackingAllocatorrebind_alloc
0赞 Steven 11/11/2023
@StoryTeller-UnslanderMonica 是的 - 我会用我得到的错误更新我的问题;但它也需要能够在原始声明中采用任意类型的子分配器。
1赞 StoryTeller - Unslander Monica 11/11/2023
任意子分配器本身应该是一个有效的分配器(否则,你怎么能满足所有的分配器要求?),所以我认为你可以依赖它重新绑定它,无论它是否是标准的。std::allocator_traits
1赞 Red.Wave 11/11/2023
像这样重新绑定:你可能还需要为一般情况提供构造函数;确保默认 Copy+Move 构造函数 + 赋值。我最终会公开继承而不是组合分配器,因为现在您需要将四个 constexpr 值定义为等于它们的对应值。using other = std::allocator_traits<BaseAllocator>::rebind_alloc<U>;allocator_traits<BaseAllocator>::

答: 暂无答案