提问人:Steven 提问时间:11/11/2023 最后编辑:Steven 更新时间:11/11/2023 访问量:53
创建符合 std 的分配器,用于包装用于诊断的任意分配器
Create std-compliant allocator that wraps arbitrary allocator for diagnostics
问:
作为自定义 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 );
但我正在为两个问题而苦苦挣扎:
- 如何让现代重新绑定工作,因为 C++ 中已弃用 rebind17
- 将子分配器重新绑定到新的 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 );
}
有什么办法可以解决这个问题吗?
答: 暂无答案
评论
std::allocator_traits
吗?据推测,它应该足以让你的分配器很好地使用它。m_allocator
BaseAllocator
T
TrackingAllocator
rebind_alloc
std::allocator_traits
using other = std::allocator_traits<BaseAllocator>::rebind_alloc<U>;
allocator_traits<BaseAllocator>::