|
ANSI
C++ permits overloading global
new operator and even provides an overloaded global
new operator that has parameters (placement new).
ACIS leverages this feature to send file and line information with every call to
ACIS_NEW that allows
ACIS to track memory leaks.
|
|
|
ACIS provides a version of
ACIS_NEW which overloads global new to send along file and line information. If the class is derived from
ACIS_OBJECT,
ACIS provides a class-level overloaded new to distinguish between global new's and class level new's behavior. This is an important distinction: these two allocations follow preprocess into completely different function calls.
|
|
|
//
|
|
// This line would preprocess into the following:
|
|
//
|
|
//
|
|
// BODY *b = BODY::operator new (size, __FILE__, __LINE__, etc.) BODY;
|
|
//
|
|
BODY *b = ACIS_NEW BODY;
|
|
|
//
|
|
// This line would preprocess into the following:
|
|
//
|
|
// int *n = operator new (size, __FILE__, __LINE__, etc.) int;
|
|
//
|
|
int *n = ACIS_NEW int;
|
|
|
While
ACIS_NEW converts into an overloaded
new with file and line information,
ACIS_DELETE does something different. If the class is derived from
ACIS_OBJECT,
ACIS_DELETE converts into a class level overloaded delete. For simple data types,
ACIS_DELETE converts into global
delete. The last statement requires a critical understanding: Deleting a simple data type using
ACIS_DELETE is exactly the same as calling global delete.
|
|
|
A simple case.
|
|
|
//
|
|
// This line would preprocess into the following:
|
|
//
|
|
//
|
|
// BODY::operator delete (ptr, etc.) b;
|
|
//
|
|
ACIS_DELETE b;
|
|
|
A complex case that demonstrates the problem with not using
STD_CAST.
|
|
|
//
|
|
// This line would preprocess into the following:
|
|
//
|
|
//
|
|
// delete n;
|
|
// this will show up as a false leak!!
|
|
//
|
|
ACIS_DELETE n;
|
|
|
Since
ACIS doesn't (and should not) overload global delete, this will show up as a leak, even though the memory is being given back to the system.
|
|
|
The correct version:
|
|
|
//
|
|
// This line would preprocess into the following:
|
|
//
|
|
//
|
|
// ACIS_STD_TYPE_OBJECT::operator delete n;
|
|
//
|
|
ACIS_DELETE STD_CAST n;
|
|
|
The
ACIS_STD_TYPE_OBJECT is defined as follows:
|
|
|
class DECL_BASE ACIS_STD_TYPE_OBJECT {
|
|
public:
|
|
void operator delete(void * alloc_ptr ) {
|
|
|
acis_discard( alloc_ptr, eClassStd, 0 );
|
|
}
|
|
|
void operator delete [](void * alloc_ptr ) {
|
|
|
acis_discard( alloc_ptr, eClassArrayStd, 0 );
|
|
}
|
|
};
|
|
|
Since the pointer is casted to an object that has an overloaded delete, the
ACIS_DELETE call is redirected to the
ACIS memory manager and handled properly.
|