Thread: Call destructor from memory manager

  1. #1
    Registered User
    Join Date
    Jan 2006
    Location
    Sweden
    Posts
    92

    Call destructor from memory manager

    Hi

    I'm writing a memory manager and I wonder if it possible to call the destructor of an object (assuming I know it has one) from the memory manager?
    The memory manager allocates a big chunk of memory and then divide it into smaller pieces as it recieves requests for allocations. Each piece of allocated memory is preceeded by a header which containes some data.

    Would appreciate some help here

    Regards
    Daniel

  2. #2
    Registered User
    Join Date
    Jan 2005
    Posts
    7,366
    All objects have destructors. You should probably only be calling the destructor if you are using placement new, which you might be doing if you have a memory manager. See this FAQ (and the others on that page) for more information:

    http://www.parashift.com/c++-faq-lit...html#faq-11.10

  3. #3
    Registered User
    Join Date
    Jan 2006
    Location
    Sweden
    Posts
    92
    That was good reading but I'm afraid I didn't find what I was looking for (maybe I haven't been looking hard enough), and after reading my first post again I realized it was a bit... fuzzy. Here's is a better description of my problem.

    I'm using a mark-sweep memory manager which, in the beginning of the program, allocates a big chunk of memory. I have then overloaded the new operator so that I can simply call the memory managers allocate method by writing:
    Code:
    Foo* foo = new Foo;
    
    //I haven't got the code right here, but it looks something like:
    void * operator new(size_t nBytes)
    {
        return g_pMemMgr->alloc(nBytes);
    }
    The memory manager then finds a suitable block, splits it if necessary, and returns the memory address. When I no longer need to use this foo variable I just leave it right where it is. The memory manager then looks through the whole memory after pointers to the blocks of memory it has. If it doesn't find a pointer to a certain block it flags it as free. At that place I want the memory manager itself to call the proper destructor of a void* type memory piece. I have read this is possible but the author of the article didn't really say how, and my attempts at using google has failed utterly.

    Thanks for your response though, it was very interesting reading!
    After reading it I begin to wonder if even the contructors of my objects are called, got to check that.

  4. #4
    Registered User
    Join Date
    May 2007
    Posts
    147
    The general description of your design is suggestive of a garbage collector, but it is widely recognized that such constructions are in opposition to some of the basic principles of C++ objects (the tightly coupled constructor/destructor cycle of objects).

    What would happen, for example, if a destructor were called because the object so allocated were explicitly deleted?

    Let me ask, then, what is the overall goal of implementing the custom allocator?

    Is it speed?

    Custom allocators are a well known practice in C++. Stroustrup indicated that performance gains can be an order of magnitude (there are times when performance gains of 10x are realized). The STL has provisions for supplying a custom allocator for certain container types (strings, for example).

    Another purpose of custom allocation is to reduce fragmentation of the heap. By taking control of allocation (away from the general CRT allocator upon which new is based), one can organize allocations in a way that avoid some of the fragmentation issues that occasionally affect runtime limits. This particular problem is more noticeable in smaller systems (either older desktop/laptop machines or embedded systems). Typical modern desktop computers have enough RAM that usually the problems associated with fragmentation of the heap simply don't occur. Certainly there are exceptions.

    I've written custom allocation engines myself, primarily to help with these two issues (performance more than fragmentation), but all of those solutions did not venture to violate the destructor cycle common to C++ practices.

    So what is your purpose in delayed destruction? Why is your design goal motivated in this direction?

    BTW, a destructor must be performed on a known type if the destructor function is to be called. Calling a destructor on a void type could never 'find' the correct destructor to call, so it's a dead end (if I understood that part of your inquiry).

  5. #5
    Registered User
    Join Date
    Jan 2005
    Posts
    7,366
    I think 11.14 in that FAQ looks like an example of exactly what you're trying to do. Creating a pool allocation manager and overloading operator new and operator delete to use the pool of memory rather than the default memory management.

    Whether its necessary or appropriate for your situation is another question, but that should be a good run-through of the major issues.

  6. #6
    Registered User
    Join Date
    Jan 2006
    Location
    Sweden
    Posts
    92
    The purpose of this manager is to keep it automated, and avoid memory leaks. I have tried to write a "fast" manager before, but it ended up being 2x slower than new/delete. So this one isn't targeted at performance, and I don't really care about fragmentation.

    The author of the article I mentioned explained it this way:
    Quote Originally Posted by Bill Blunden
    To institute this type of functionality with my mark-sweep collector,
    you might want to consider adding another field to the memory
    block header.

    This new field, which we’ll call TYPE, indicates if the memory block
    is an object, and if it is, then it indexes an element in an array of
    function pointers. These function pointers store the addresses of
    destructor functions. This setup is displayed in Figure 5.12.

    When a memory block is about to be reclaimed, the garbage collector
    will check to see if the memory block represents an object. If
    the memory block is an object, the collector will invoke the object’s
    destructor before it reclaims the memory block’s storage.
    Naturally, there are many more details to consider than I’ve mentioned,
    such as setting up the table of function pointers and handling
    nested objects that call different destructors. You will have to experiment
    with a number of different approaches. Nevertheless, I hope
    to have guided you in the right direction.
    From this I found out that I might want to access the virtual function table, got to find out on how to do that.

    Thanks for your replies, I'll try writing something up tomorrow and return with hopefully good news. After I've got that working I just need to rewrite this manager a few times

    Regards
    Daniel

  7. #7
    Registered User
    Join Date
    May 2007
    Posts
    147
    Have you considered smart pointers instead?

    Reference counted smart pointers provide the two primary goals you've indicated, with very little hassle - and the concept supports threaded work.

  8. #8
    Registered User
    Join Date
    Jan 2006
    Location
    Sweden
    Posts
    92
    I have been thinking about it, and thought it was a good idea. But then I read this article and the author liked the mark-sweep method more. But now that you mention it, I'm not sure if this manager supports threads - which I'm going to use in its environment.

    Well, screw this. I'll go with boost instead (I simply can't resist putting at least one smiley in each post)

    Thanks for all your thoughs and suggestions!

    Regards
    Daniel
    Last edited by The Wazaa; 05-22-2007 at 12:09 AM.

  9. #9
    Registered User
    Join Date
    May 2007
    Posts
    147
    I think you'll be better served.

    Memory management is a 'dark science' of sorts, and there's almost no performance benefit to generalized managers. The performance benefit kicks in when you can make the assumption all of the allocated items are of the same size, which is one reason you can overload the new operator of a class.

    Smart pointers make memory management much safer than C style memory management. For one, they automatically delete objects when they fall from scope, and they usually auto initialize to NULL.

    Reference counted pointers allow you to toss off items to other threads without bothering to meticulously plan out what thread ends up deleting the object when it's done. Sometimes it's just not convenient to have to think that way. With reference counting you can stop thinking about it - the last one out deletes.

    You can still override new and delete for custom allocation of classes if you need speed, or to control fragmentation - but it generally doesn't come up.

    I'll close with the hint of a final thought about custom allocation. Some time ago I did experimental work on multi-core threaded systems where occasionally performance was critical under situations where thousands of small/medium sized objects are churned (allocated/freed/allocated). An obvious candidate for a custom allocator optimization. Experiment proved that one point of contention is memory allocation - that is, there's one heap, and it's usually locked during allocation. The more cores you have, the more likely it is, when code like that runs, that all processors are locking the heap, piling up in a queue behind each other, effectively killing parallel performance benefit.

    Our solution was to multiplex the allocator. Thread local storage generated a local cache of available memory per thread, so that the general heap was locked only once every few hundred allocations. On an 8 core system, when this condition dropped performance from what was expected to be 100% of all 8 cores, down to 1/8 on each (as they queued behind each other), our allocator returned 99.9% performance from all 8 CPU's. The system still used smart pointers (which were also on the custom allocators), no garbage collection - the secret was multiplexed/thread local cache distribution from the heap. It's tricky, but was worth it for that application, and several others similar to it we developed since.
    Last edited by JVene; 05-22-2007 at 12:19 AM.

Popular pages Recent additions subscribe to a feed

Similar Threads

  1. Relate memory allocation in struct->variable
    By Niara in forum C Programming
    Replies: 4
    Last Post: 03-23-2007, 03:06 PM
  2. Multiple types in lists, vectors or arrays.
    By megatron09 in forum C++ Programming
    Replies: 20
    Last Post: 08-31-2006, 01:54 PM
  3. I have the Memory Address of a function, how do I call it?
    By vulcan_146 in forum C++ Programming
    Replies: 8
    Last Post: 05-22-2005, 02:00 AM
  4. Is it necessary to write a specific memory manager ?
    By Morglum in forum Game Programming
    Replies: 18
    Last Post: 07-01-2002, 01:41 PM
  5. Pls help me to do this project in C I need source code
    By sureshmenon74 in forum C Programming
    Replies: 4
    Last Post: 10-04-2001, 06:57 AM