Quick Links: |
Provide scoped guard to temporarily change the default allocator. More...
Namespaces | |
namespace | bslma |
Typedefs | |
typedef bslma::DefaultAllocatorGuard | bslma_DefaultAllocatorGuard |
bslma::DefaultAllocatorGuard | default-allocator scoped guard |
bslma::DefaultAllocatorGuard
, that serves as a "scoped guard" to enable the temporary replacement of the process-wide default allocator. This functionality is intended for testing only, and in no event should this component be used except in main
. bslma::Allocator
. The default allocator at the time of guard construction is held by the guard, and the constructor-argument allocator is installed as the new process-wide default allocator (via a call to bslma::Default::setDefaultAllocatorRaw
). Upon destruction of the guard object, its held allocator is restored as the process-wide default allocator (via another call to bslma::Default::setDefaultAllocatorRaw
). bslma_default
component ensures that, unless the owner of main
or some intervening code explicitly installs a default allocator, the bslma::NewDeleteAllocator::singleton()
will be the default allocator for that process (i.e., calls to bslma::Default::defaultAllocator()
will return the new-delete allocator unless someone has set the default allocator to a different allocator intentionally). Consider for purposes of this illustrative example the case where we, as owners of a test driver main
, can count on the bslma::NewDeleteAllocator
singleton being the default. new
and delete
, and that also keeps count of the number of memory blocks that have been allocated but never deallocated. (Note that, in testing real production code, bslma::TestAllocator
serves this purpose.) class my_CountingAllocator : public bslma::Allocator { int d_blocksOutstanding; public: my_CountingAllocator(); ~my_CountingAllocator(); virtual void *allocate(int size); virtual void deallocate(void *address); int blocksOutstanding() const { return d_blocksOutstanding; } }; inline my_CountingAllocator::my_CountingAllocator() : d_blocksOutstanding(0) { } inline my_CountingAllocator::~my_CountingAllocator() { if (0 < d_blocksOutstanding) { std::cout << "***ERROR: Memory Leak***" << std::endl << d_blocksOutstanding << " block(s) leaked. " << "Program aborting." << std::endl; assert(0); } } inline void *my_CountingAllocator::allocate(int size) { ++d_blocksOutstanding; return operator new(size); } inline void my_CountingAllocator::deallocate(void *address) { --d_blocksOutstanding; operator delete(address); }
bslma::Allocator
and the bslma::Default
mechanism. First, we confirm that the bslma::NewDeleteAllocator
singleton is indeed installed. //my_component.t.cpp // ... int main() { // ... bslma::NewDeleteAllocator *na = &bslma::NewDeleteAllocator::singleton(); assert(na == bslma::Default::defaultAllocator());
{ my_CountingAllocator testAllocator; bslma::DefaultAllocatorGuard guard(&testAllocator); assert(&testAllocator == bslma::Default::defaultAllocator()); // Create and test the object under test, which will use the // test allocator *by* *default*. // ... } assert(na == bslma::Default::defaultAllocator());
stdout
and abort. Otherwise, the new-delete allocator will be re-installed as the default allocator, and the program will proceed to the next block of code.