Custom destructors -- memory management

D

Dave Rahardja

I need to design a container that must hold a set of references to a variety
of object types, managed by different memory managers. At some time, the
container must destroy each object. Currently I have the following design in
mind:


class Destructible // interface
{
public:
virtual void destroy() = 0;
};


class Container
{
public:
// ...

void add(Destructible& item);

// ...
void destroy();
};

void Container::destroy()
{
// ... iterate ...
items.destroy();
}


// An item in the container
class Item: virtual public Destructible
{
public:
virtual void destroy();
};

void Item::destroy()
{
MyMemoryManager::Lock lock(this);
~Item();
}


Is there an easier way to do this? Is there a way to make the container work
with objects without a custom destructor?

-dr
 
?

=?iso-8859-1?q?Erik_Wikstr=F6m?=

I need to design a container that must hold a set of references to a variety
of object types, managed by different memory managers. At some time, the
container must destroy each object. Currently I have the following design in
mind:

class Destructible // interface
{
public:
virtual void destroy() = 0;

};

class Container
{
public:
// ...

void add(Destructible& item);

// ...
void destroy();

};

void Container::destroy()
{
// ... iterate ...
items.destroy();

}

// An item in the container
class Item: virtual public Destructible
{
public:
virtual void destroy();

};

void Item::destroy()
{
MyMemoryManager::Lock lock(this);
~Item();

}

Is there an easier way to do this? Is there a way to make the container work
with objects without a custom destructor?


Maybe I missed some of the requirements but what's wrong with just
using the normal destructor? If the container uses any of the standard
containers then the destructor will be called automatically. If you
are using pointers then the destructor will be called on delete.

Have you perhaps been using some garbagecollected language like Java
or C# where you don't know when an object is destroyed? Well, in C++
you do, so all you have to worry about is to make sure that the object
is destroyed (going out of scope or using delete on a pointer) and
that the destructor cleans up the stuff that needs to be cleaned up.
 
W

wo

// ... iterate ...
items.destroy();


Have you ever considered using iterators ? You might want to google
for "C++ iterator" in order to do such traversal. items is the C
way of seeing the problem, which isn't really the best one for
containers where random access (using the [] operator) isn't
available, like lists.
 
D

Dave Rahardja

Maybe I missed some of the requirements but what's wrong with just
using the normal destructor? If the container uses any of the standard
containers then the destructor will be called automatically. If you
are using pointers then the destructor will be called on delete.

Have you perhaps been using some garbagecollected language like Java
or C# where you don't know when an object is destroyed? Well, in C++
you do, so all you have to worry about is to make sure that the object
is destroyed (going out of scope or using delete on a pointer) and
that the destructor cleans up the stuff that needs to be cleaned up.

I'm sorry if I wasn't clear--it wasn't the destructor call that I was worried
about. It is that each of the elements in this container may be allocated by a
_different_ memory manager. Thus, using global delete may not be appropriate
for all elements.

-dr
 
D

Dave Rahardja

// ... iterate ...
items.destroy();


Have you ever considered using iterators ? You might want to google
for "C++ iterator" in order to do such traversal. items is the C
way of seeing the problem, which isn't really the best one for
containers where random access (using the [] operator) isn't
available, like lists.


Since I am _providing_ the container, I think I should be free to use whatever
traversal method I like internally! ;-)

Joking aside, the traversal is not the question here. I merely used the []
notation to suggest that there is some sort of iteration going on internally
when the objects are destroyed.

The question I'm asking is about how to destroy these objects, which may have
been allocated on a variety of memory managers.

-dr
 
J

James Kanze

On 2 Apr 2007 23:36:11 -0700, "Erik Wikström" <[email protected]>
wrote:
I'm sorry if I wasn't clear--it wasn't the destructor call
that I was worried about. It is that each of the elements in
this container may be allocated by a _different_ memory
manager. Thus, using global delete may not be appropriate for
all elements.

How do you know which memory manager is responsible for a given
object? If it is purely a function of the type, then using a
common base class, and providing an operator delete member
function in the class should do the trick; you just use delete,
as normal, and the compiler takes care of the rest. Failing
that, you need some means of tracking which memory manager is
responsible for which bit of memory. The most frequent solution
for this is to use some hidden memory in front of the allocated
block. You then replace the global new and delete functions to
set this memory, and to use it when they are called. Say
something along the lines of:

union BlockHeader
{
MemoryManager* owner ;
double dummyForAlignment ; // may need something more
// for some processors...
} ;

void* operator new( size_t n )
{
BlockHeader* result =
static_cast< BlockHeader * >(
::malloc( n + sizeof( BlockHeader ) ) ) ;
if ( result == NULL ) {
throw std::bad_alloc() ;
}
result->owner = NULL ;
return result + 1 ;
}

void* operator new( size_t n, MemoryManager* from )
{
BlockHeader* result =
static_cast< BlockHeader * >(
from->alloc( n + sizeof( BlockHeader ) ) ) ;
if ( result == NULL ) {
throw std::bad_alloc() ;
}
result->owner = from ;
return result + 1 ;
}

void operator delete( void* p )
{
BlockHeader* block
= static_cast< BlockHeader* >( p ) - 1 ;
if ( block->owner == NULL ) {
::free( block ) ;
} else {
block->owner->free( block ) ;
}
} ;

Again, this takes care of everything automatically. You
allocate with new or new(memmgr), and you delete as usual.
 
D

Dave Rahardja

How do you know which memory manager is responsible for a given
object? If it is purely a function of the type, then using a
common base class, and providing an operator delete member
function in the class should do the trick; you just use delete,
as normal, and the compiler takes care of the rest. Failing
that, you need some means of tracking which memory manager is
responsible for which bit of memory. The most frequent solution
for this is to use some hidden memory in front of the allocated
block. You then replace the global new and delete functions to
set this memory, and to use it when they are called. Say
something along the lines of:
Again, this takes care of everything automatically. You
allocate with new or new(memmgr), and you delete as usual.

Hey that's a great idea! That might just be the ticket.

-dr
 

Ask a Question

Want to reply to this thread or ask your own question?

You'll need to choose a username for the site, which only take a couple of moments. After that, you can post your question and our members will help you out.

Ask a Question

Members online

No members online now.

Forum statistics

Threads
473,755
Messages
2,569,537
Members
45,021
Latest member
AkilahJaim

Latest Threads

Top