Skip to main content
Pigweed's logo Pigweed
code_xml
  1. Home
  2. Reference
  3. C/C++
  4. pw_allocator
  5. Forwarding allocators
  6. pw::allocator::GuardedAllocator< BlockAllocatorType, LockType, ErrorHandler > Class Template Reference
Loading...
Searching...
No Matches
pw::allocator::GuardedAllocator< BlockAllocatorType, LockType, ErrorHandler > Class Template Reference

Overview

template<typename BlockAllocatorType, typename LockType = sync::NoLock, typename ErrorHandler = internal::DefaultGuardErrorHandler>
class pw::allocator::GuardedAllocator< BlockAllocatorType, LockType, ErrorHandler >

GuardedAllocator that can detect heap overflows in a thread-safe manner.

This class takes a BlockAllocator and manages concurrent access to it. This allows a background thread to validate allocations using one of two key methods:

  • ValidateOne will validate a single block each time it is called. Successive calls will eventually iterate over all blocks.
  • ValidateAll vill validate all current blocks. Other allocator methods will block until the validation is complete.

Both methods can be called explicitly, or used to create a thread that periodically validates, e.g.

Thread thread(options, [&guarded_allocator]() {
while (true) {
guarded_allocator.ValidateOne();
pw::this_thread::sleep_for(500ms);
}
});
Definition: thread.h:69

Note that while this allocator wraps a BlockAllocator it is NOT a block allocator itself. In particular, pointers allocated from this allocator MUST NOT be passed to methods like BlockType::FromUsableSpace.

Template Parameters
BlockAllocatorTypeAllocator derived from BlockAllocator.
LockTypeSync primitive link, e.g. sync::Mutex.
ErrorHandlerUsed to report guard validation errors.
Inheritance diagram for pw::allocator::GuardedAllocator< BlockAllocatorType, LockType, ErrorHandler >:
pw::allocator::ForwardingAllocator pw::Allocator pw::Deallocator

Public Types

using BlockType = typename BlockAllocatorType::BlockType
 
- Public Types inherited from pw::Allocator
using Fragmentation = allocator::Fragmentation
 
- Public Types inherited from pw::Deallocator
using Capabilities = allocator::Capabilities
 
using Capability = allocator::Capability
 
using Layout = allocator::Layout
 

Public Member Functions

constexpr GuardedAllocator (BlockAllocatorType &allocator)
 
BlockType * ValidateOne ()
 
BlockType * ValidateAll ()
 
- Public Member Functions inherited from pw::Allocator
void * Allocate (Layout layout)
 
template<typename T , int &... kExplicitGuard, std::enable_if_t<!std::is_array_v< T >, int > = 0, typename... Args>
T * New (Args &&... args)
 
template<typename T , int &... kExplicitGuard, typename ElementType = std::remove_extent_t<T>, std::enable_if_t< is_bounded_array_v< T >, int > = 0>
ElementType * New ()
 
template<typename T , int &... kExplicitGuard, typename ElementType = std::remove_extent_t<T>, std::enable_if_t< is_unbounded_array_v< T >, int > = 0>
ElementType * New (size_t count)
 
template<typename T , int &... kExplicitGuard, typename ElementType = std::remove_extent_t<T>, std::enable_if_t< is_unbounded_array_v< T >, int > = 0>
ElementType * New (size_t count, size_t alignment)
 Constructs an alignment-byte aligned array of count objects.
 
template<typename T , int &... kExplicitGuard, std::enable_if_t<!std::is_array_v< T >, int > = 0, typename... Args>
UniquePtr< T > MakeUnique (Args &&... args)
 
template<typename T , std::enable_if_t< is_unbounded_array_v< T >, int > = 0>
UniquePtr< T > MakeUnique (size_t size)
 
template<typename T , std::enable_if_t< is_unbounded_array_v< T >, int > = 0>
UniquePtr< T > MakeUnique (size_t size, size_t alignment)
 
template<typename T , std::enable_if_t< is_bounded_array_v< T >, int > = 0>
UniquePtr< T > MakeUnique ()
 
template<typename T , int &... kExplicitGuard, std::enable_if_t<!std::is_array_v< T >, int > = 0, typename... Args>
SharedPtr< T > MakeShared (Args &&... args)
 
template<typename T , std::enable_if_t< is_unbounded_array_v< T >, int > = 0>
SharedPtr< T > MakeShared (size_t size)
 
template<typename T , std::enable_if_t< is_unbounded_array_v< T >, int > = 0>
SharedPtr< T > MakeShared (size_t size, size_t alignment)
 
template<typename T , std::enable_if_t< is_bounded_array_v< T >, int > = 0>
SharedPtr< T > MakeShared ()
 
bool Resize (void *ptr, size_t new_size)
 
void * Reallocate (void *ptr, Layout new_layout)
 
size_t GetAllocated () const
 
std::optional< Fragmentation > MeasureFragmentation () const
 Returns fragmentation information for the allocator's memory region.
 
- Public Member Functions inherited from pw::Deallocator
constexpr const Capabilities & capabilities () const
 
constexpr bool HasCapability (Capability capability) const
 Returns whether a given capability is enabled for this object.
 
void Deallocate (void *ptr)
 
template<typename ElementType >
void DeleteArray (ElementType *ptr, size_t count)
 
template<typename ElementType >
void Destroy (ElementType *ptr, size_t count)
 
StatusWithSize GetCapacity () const
 
bool IsEqual (const Deallocator &other) const
 
template<typename T , int &... kExplicitGuard, std::enable_if_t<!std::is_array_v< T >, int > = 0>
void Delete (T *ptr)
 
template<typename T , int &... kExplicitGuard, typename ElementType = std::remove_extent_t<T>, std::enable_if_t< is_bounded_array_v< T >, int > = 0>
void Delete (ElementType *ptr)
 
template<typename T , int &... kExplicitGuard, typename ElementType = std::remove_extent_t<T>, std::enable_if_t< is_unbounded_array_v< T >, int > = 0>
void Delete (ElementType *ptr, size_t count)
 

Protected Member Functions

void * DoAllocate (Layout layout) override
 
void DoDeallocate (void *ptr) override
 
bool DoResize (void *ptr, size_t new_size) override
 
void * DoReallocate (void *ptr, Layout new_layout) override
 
- Protected Member Functions inherited from pw::allocator::ForwardingAllocator
constexpr ForwardingAllocator (const Capabilities &capabilities) noexcept
 
constexpr ForwardingAllocator (pw::Allocator &allocator) noexcept
 
constexpr void Init (pw::Allocator &allocator)
 
constexpr pw::Allocator & allocator ()
 
constexpr const pw::Allocator & allocator () const
 
void * DoAllocate (Layout layout) override
 
void DoDeallocate (void *ptr) override
 
bool DoResize (void *ptr, size_t new_size) override
 
bool DoBeforeReallocate (void *ptr, Layout new_layout) override
 
void DoAfterReallocateCopy (void *ptr, Layout new_layout, void *new_ptr) override
 
void DoAfterReallocateDone (Layout new_layout, void *new_ptr) override
 
size_t DoGetAllocated () const override
 
std::optional< Fragmentation > DoMeasureFragmentation () const override
 Returns fragmentation information for the allocator's memory region.
 
Result< Layout > DoGetInfo (InfoType info_type, const void *ptr) const override
 
- Protected Member Functions inherited from pw::Allocator
constexpr Allocator () noexcept=default
 TODO(b/326509341): Remove when downstream consumers migrate.
 
constexpr Allocator (const Capabilities &capabilities) noexcept
 
virtual void * DoAllocate (Layout layout)=0
 
virtual bool DoResize (void *ptr, size_t new_size)
 
virtual void * DoReallocate (void *ptr, Layout new_layout)
 
virtual bool DoBeforeReallocate (void *ptr, Layout new_layout)
 
virtual void DoAfterReallocateCopy (void *ptr, Layout new_layout, void *new_ptr)
 
virtual void DoAfterReallocateDone (Layout new_layout, void *new_ptr)
 
virtual size_t DoGetAllocated () const
 
virtual std::optional< Fragmentation > DoMeasureFragmentation () const
 Returns fragmentation information for the allocator's memory region.
 
- Protected Member Functions inherited from pw::Deallocator
constexpr Deallocator ()=default
 TODO(b/326509341): Remove when downstream consumers migrate.
 
constexpr Deallocator (const Capabilities &capabilities)
 
Result< Layout > GetInfo (InfoType info_type, const void *ptr) const
 
Result< Layout > GetRequestedLayout (const void *ptr) const
 
Result< Layout > GetUsableLayout (const void *ptr) const
 
Result< Layout > GetAllocatedLayout (const void *ptr) const
 
bool Recognizes (const void *ptr) const
 
virtual void DoDeallocate (void *ptr)=0
 
virtual Result< Layout > DoGetInfo (InfoType, const void *) const
 

Additional Inherited Members

- Protected Types inherited from pw::Deallocator
enum class  InfoType {
  kRequestedLayoutOf , kUsableLayoutOf , kAllocatedLayoutOf , kCapacity ,
  kRecognizes
}
 
- Static Protected Member Functions inherited from pw::Allocator
static bool BeforeReallocate (Allocator &allocator, void *ptr, Layout new_layout)
 
static void AfterReallocateCopy (Allocator &allocator, void *ptr, Layout new_layout, void *new_ptr)
 
static void AfterReallocateDone (Allocator &allocator, Layout new_layout, void *new_ptr)
 
- Static Protected Member Functions inherited from pw::Deallocator
static Result< Layout > GetInfo (const Deallocator &deallocator, InfoType info_type, const void *ptr)
 
static Result< Layout > GetRequestedLayout (const Deallocator &deallocator, const void *ptr)
 
static Result< Layout > GetUsableLayout (const Deallocator &deallocator, const void *ptr)
 
static Result< Layout > GetAllocatedLayout (const Deallocator &deallocator, const void *ptr)
 
static bool Recognizes (const Deallocator &deallocator, const void *ptr)
 
- Static Protected Attributes inherited from pw::Deallocator
template<typename T >
static constexpr bool is_bounded_array_v = ::pw::is_bounded_array_v<T>
 
template<typename T >
static constexpr bool is_unbounded_array_v = ::pw::is_unbounded_array_v<T>
 

Member Function Documentation

◆ DoAllocate()

template<typename BlockAllocatorType , typename LockType = sync::NoLock, typename ErrorHandler = internal::DefaultGuardErrorHandler>
void * pw::allocator::GuardedAllocator< BlockAllocatorType, LockType, ErrorHandler >::DoAllocate ( Layout  layout)
inlineoverrideprotectedvirtual

Allocates a block of memory with the specified size and alignment.

Returns nullptr if the allocation cannot be made, or the layout has a size of 0.

Parameters
[in]layoutDescribes the memory to be allocated.

Reimplemented from pw::allocator::ForwardingAllocator.

◆ DoDeallocate()

template<typename BlockAllocatorType , typename LockType , typename ErrorHandler >
void pw::allocator::GuardedAllocator< BlockAllocatorType, LockType, ErrorHandler >::DoDeallocate ( void *  ptr)
overrideprotectedvirtual

Releases a previously-allocated block of memory.

The given pointer must have been previously provided by this memory resource; otherwise the behavior is undefined.

Parameters
[in]ptrPointer to previously-allocated memory.

Reimplemented from pw::allocator::ForwardingAllocator.

◆ DoReallocate()

template<typename BlockAllocatorType , typename LockType , typename ErrorHandler >
void * pw::allocator::GuardedAllocator< BlockAllocatorType, LockType, ErrorHandler >::DoReallocate ( void *  ptr,
Layout  new_layout 
)
overrideprotectedvirtual

Modifies the size of a previously-allocated block of memory.

Returns pointer to the modified block of memory, or nullptr if the memory could not be modified.

The data stored by the memory being modified must be trivially copyable. If it is not, callers should themselves attempt to Resize, then Allocate, move the data, and Deallocate as needed.

If nullptr is returned, the block of memory is unchanged. In particular, if the new_layout has a size of 0, the given pointer will NOT be deallocated.

TODO(b/331290408): This error condition needs to be better communicated to module users, who may assume the pointer is freed.

Unlike Resize, providing a null pointer will return a new allocation.

If the request can be satisfied using Resize, the alignment parameter may be ignored.

Parameters
[in]ptrPointer to previously-allocated memory.
[in]new_layoutDescribes the memory to be allocated.

Reimplemented from pw::Allocator.

◆ DoResize()

template<typename BlockAllocatorType , typename LockType , typename ErrorHandler >
bool pw::allocator::GuardedAllocator< BlockAllocatorType, LockType, ErrorHandler >::DoResize ( void *  ptr,
size_t  new_size 
)
overrideprotectedvirtual

Modifies the size of an previously-allocated block of memory without copying any data.

Returns true if its size was changed without copying data to a new allocation; otherwise returns false.

In particular, it always returns true if the old_layout.size() equals new_size, and always returns false if the given pointer is null, the old_layout.size() is 0, or the new_size is 0.

Parameters
[in]ptrPointer to previously-allocated memory.
[in]new_sizeRequested new size for the memory allocation.

Reimplemented from pw::allocator::ForwardingAllocator.

◆ ValidateAll()

template<typename BlockAllocatorType , typename LockType , typename ErrorHandler >
auto pw::allocator::GuardedAllocator< BlockAllocatorType, LockType, ErrorHandler >::ValidateAll

Checks for heap overflows in all current allocations.

This method may be called explicitly, or repeatedly from a background thread. Other allocator methods will block until the validation is complete.

Returns
A pointer to the block with a corrupted prefix and/or suffix.

◆ ValidateOne()

template<typename BlockAllocatorType , typename LockType , typename ErrorHandler >
auto pw::allocator::GuardedAllocator< BlockAllocatorType, LockType, ErrorHandler >::ValidateOne

Checks for heap overflows in an allocation.

This method may be called explicitly, or repeatedly from a background thread. The individual allocation being checked is not specified, but repeated calls will eventually iterate over all blocks.

Returns
A pointer to the block with a corrupted prefix and/or suffix.

The documentation for this class was generated from the following file: