Provide an exception class for memory allocation operations.
More...
Namespaces |
namespace | bslma |
Detailed Description
- Outline
-
-
- Purpose:
- Provide an exception class for memory allocation operations.
-
- Classes:
-
-
- Description:
- This component defines a simple exception object for testing exceptions during memory allocation operations. The exception object
bslma::TestAllocatorException
contains information about the allocation request, which can be queried for by the "catcher" of this exception.
-
- Usage:
- In the following example, the
bslma::TestAllocatorException
object is thrown by the allocate
method of the my_Allocator
object after the number of allocation requests exceeds the allocator's allocation limit. This example demonstrates how to use a user-defined allocator (e.g., my_Allocator
) and bslma::TestAllocatorException
to verify that an object (e.g., my_ShortArray
) under test is exception-neutral:
#include <bslma_allocator.h>
class my_Allocator : public bslma::Allocator {
int d_allocationLimit;
private:
my_Allocator(const my_Allocator&);
my_Allocator& operator=(const my_Allocator&);
public:
my_Allocator() : d_allocationLimit(-1) {}
~my_Allocator() {}
void *allocate(int size);
void deallocate(void *address) { free(address); }
void setAllocationLimit(int limit){ d_allocationLimit = limit; }
int allocationLimit() const { return d_allocationLimit; }
};
#include <my_allocator.h>
void *my_Allocator::allocate(int size)
{
#ifdef BDE_BUILD_TARGET_EXC
if (0 <= d_allocationLimit) {
--d_allocationLimit;
if (0 > d_allocationLimit) {
throw bslma::TestAllocatorException(size);
}
}
#endif
return (void *)malloc(size);
}
Note that the macro BDE_BUILD_TARGET_EXC
is defined at compile-time to indicate whether exceptions are enabled. In the above code, if exceptions are not enabled, the code that throws bslma::TestAllocatorException
is never executed. The following is the test driver for my_ShortArray
.
- Note that "\$" must be replaced by "\" in the preprocessor macro definitions that follow. The "$" symbols are present in this header file to avoid a diagnostic elicited by some compilers (e.g., "warning: multi-line comment").
#include <my_shortarray.h>
#include <my_testallocator.h>
#include <bslma_testallocatorexception.h>
#ifdef BDE_BUILD_TARGET_EXC
#define BSLMA_TESTALLOCATOR_EXCEPTION_TEST_BEGIN { \$
{ \$
static int firstTime = 1; \$
if (veryVerbose && firstTime) std::cout << \$
"### BSLMA EXCEPTION TEST -- (ENABLED) --" << std::endl; \$
firstTime = 0; \$
} \$
if (veryVeryVerbose) std::cout << \$
"### Begin bslma exception test." << std::endl; \$
int bslmaExceptionCounter = 0; \$
static int bslmaExceptionLimit = 100; \$
testAllocator.setAllocationLimit(bslmaExceptionCounter); \$
do { \$
try {
#define BSLMA_TESTALLOCATOR_EXCEPTION_TEST_END \$
} catch (bslma::TestAllocatorException& e) { \$
if (veryVerbose && bslmaExceptionLimit || veryVeryVerbose) { \$
--bslmaExceptionLimit; \$
std::cout << "(*** " << bslmaExceptionCounter << ')'; \$
if (veryVeryVerbose) { std::cout << " BSLMA_EXCEPTION: " \$
<< "alloc limit = " << bslmaExceptionCounter << ", " \$
<< "last alloc size = " << e.numBytes(); \$
} \$
else if (0 == bslmaExceptionLimit) { \$
std::cout << " [ Note: 'bslmaExceptionLimit' reached. ]";\$
} \$
std::cout << std::endl; \$
} \$
testAllocator.setAllocationLimit(++bslmaExceptionCounter); \$
continue; \$
} \$
testAllocator.setAllocationLimit(-1); \$
break; \$
} while (1); \$
if (veryVeryVerbose) std::cout << \$
"### End bslma exception test." << std::endl; \$
}
#else
#define BSLMA_TESTALLOCATOR_EXCEPTION_TEST_BEGIN \$
{ \$
static int firstTime = 1; \$
if (verbose && firstTime) { std::cout << \$
"### BSLMA EXCEPTION TEST -- (NOT ENABLED) --" << std::endl; \$
firstTime = 0; \$
} \$
}
#define BSLMA_TESTALLOCATOR_EXCEPTION_TEST_END
#endif
static
bool areEqual(const short *array1, const short *array2, int numElement)
{
for (int i = 0; i < numElement; ++i) {
if (array1[i] != array2[i]) return false;
}
return true;
}
int main(int argc, char *argv[]) {
int test = argc > 1 ? atoi(argv[1]) : 0;
int verbose = argc > 2;
int veryVerbose = argc > 3;
int veryVeryVerbose = argc > 4;
my_Allocator testAllocator;
switch (test) { case 0:
case 6: {
struct {
int d_line;
int d_numElem;
short d_exp[NUM_VALUES];
} DATA[] = {
{ L_, 0, {} },
{ L_, 1, { V0 } },
{ L_, 5, { V0, V1, V2, V3, V4 } }
};
const int NUM_TEST = sizeof DATA / sizeof *DATA;
for (int ti = 0; ti < NUM_TEST; ++ti) {
const int LINE = DATA[ti].d_line;
const int NUM_ELEM = DATA[ti].d_numElem;
const short *EXP = DATA[ti].d_exp;
BSLMA_TESTALLOCATOR_EXCEPTION_TEST_BEGIN {
my_ShortArray mA(&testAllocator);
const my_ShortArray& A = mA;
for (int ei = 0; ei < NUM_ELEM; ++ei) {
mA.append(VALUES[ei]);
}
if (veryVerbose) { P_(ti); P_(NUM_ELEM); P(A); }
LOOP2_ASSERT(LINE, ti, areEqual(EXP, A, NUM_ELEM));
} BSLMA_TESTALLOCATOR_EXCEPTION_TEST_END
}
if (veryVerbose) std::cout << testAllocator << std::endl;
} break;
}
}