Horrid Memory Management Issue
-
Hi all, back with a slightly different issue. OK, here's what I'm trying to do: I'm writing a template container class for a dynamic array (similar to the vector class). The class will be used as a basis for my own custom string allocation and more complex class structures. With this in mind, operator new in its standard form has not been implemented because it cannot be used to expand memory, I would, in effect, have to new another block of memory and copy the contents over before deleting the old block, this is slow and prone to mistakes. Therefore malloc has been implemented, with realloc, to handle the actual memory allocations. However, the problem with malloc is that it never calls the constructor for the object you want to store, it just allocates raw bytes. BUT, does this mean I could use placement new to initialise a block of memory with type T as follows:
T* p = malloc(sizeof(T)); if(p) { new (p) T; }
I would like to be able to call the constructor for each object in the malloc'ated area but similarly I can't use new cos I want it to be fast AND dynamic. Any good links, ideas, suggestions on how I'm going about this would be very much appreciated. This class will be a foundation for many things and I need it to be neat, at the moment it works, but its buggy cos things aren't getting constructed properly. Thanks guys. -
Hi all, back with a slightly different issue. OK, here's what I'm trying to do: I'm writing a template container class for a dynamic array (similar to the vector class). The class will be used as a basis for my own custom string allocation and more complex class structures. With this in mind, operator new in its standard form has not been implemented because it cannot be used to expand memory, I would, in effect, have to new another block of memory and copy the contents over before deleting the old block, this is slow and prone to mistakes. Therefore malloc has been implemented, with realloc, to handle the actual memory allocations. However, the problem with malloc is that it never calls the constructor for the object you want to store, it just allocates raw bytes. BUT, does this mean I could use placement new to initialise a block of memory with type T as follows:
T* p = malloc(sizeof(T)); if(p) { new (p) T; }
I would like to be able to call the constructor for each object in the malloc'ated area but similarly I can't use new cos I want it to be fast AND dynamic. Any good links, ideas, suggestions on how I'm going about this would be very much appreciated. This class will be a foundation for many things and I need it to be neat, at the moment it works, but its buggy cos things aren't getting constructed properly. Thanks guys.Well, first off, I've gotta say thanks - I learnt a new thing today - I was never aware of the placement syntax :/ Mixing C-style and C++ style memory allocations is not a good idea since they use separate memory managers. You could replace your
malloc(sizeof(T))
withnew char[sizeof(T)]
.Realloc
would still present you with the copying problem - infact, ifrealloc
can't extend the memory area it will create a completely new area and perform a copy operation. It does look like the placement syntax enables you to give an explicit address for the object you wish to dynamically create - it also looks like that will remove the overhead of the memory manager actually finding a suitable sized piece of free memory. So, I am thinking you are on the right track here. [EDIT] One thing I forgot to mention was that when you do use placement new, Stroustrup states that you need to explicitly call destructors for objects when you want to delete them - this makes sense since the memory manager is being bypassed. [/EDIT] However, you may want to consider creating space for several objects each time you need to reserve space i.e.new char[N*sizeof(T)]
. Now create you own memory management scheme that uses that pool of memory with placement new. When that area is exhausted, create another pool. This has the effect of reducing the number of times the standardnew
operator needs to be called - thus reducing overhead. Ok, you have to manage each pool but working with fixed sized objects within each pool should be fairly efficient to to. There is a book called "Efficient C++" which looks at these issues in some detail. Hope this helps Phil -
Hi all, back with a slightly different issue. OK, here's what I'm trying to do: I'm writing a template container class for a dynamic array (similar to the vector class). The class will be used as a basis for my own custom string allocation and more complex class structures. With this in mind, operator new in its standard form has not been implemented because it cannot be used to expand memory, I would, in effect, have to new another block of memory and copy the contents over before deleting the old block, this is slow and prone to mistakes. Therefore malloc has been implemented, with realloc, to handle the actual memory allocations. However, the problem with malloc is that it never calls the constructor for the object you want to store, it just allocates raw bytes. BUT, does this mean I could use placement new to initialise a block of memory with type T as follows:
T* p = malloc(sizeof(T)); if(p) { new (p) T; }
I would like to be able to call the constructor for each object in the malloc'ated area but similarly I can't use new cos I want it to be fast AND dynamic. Any good links, ideas, suggestions on how I'm going about this would be very much appreciated. This class will be a foundation for many things and I need it to be neat, at the moment it works, but its buggy cos things aren't getting constructed properly. Thanks guys. -
Well, first off, I've gotta say thanks - I learnt a new thing today - I was never aware of the placement syntax :/ Mixing C-style and C++ style memory allocations is not a good idea since they use separate memory managers. You could replace your
malloc(sizeof(T))
withnew char[sizeof(T)]
.Realloc
would still present you with the copying problem - infact, ifrealloc
can't extend the memory area it will create a completely new area and perform a copy operation. It does look like the placement syntax enables you to give an explicit address for the object you wish to dynamically create - it also looks like that will remove the overhead of the memory manager actually finding a suitable sized piece of free memory. So, I am thinking you are on the right track here. [EDIT] One thing I forgot to mention was that when you do use placement new, Stroustrup states that you need to explicitly call destructors for objects when you want to delete them - this makes sense since the memory manager is being bypassed. [/EDIT] However, you may want to consider creating space for several objects each time you need to reserve space i.e.new char[N*sizeof(T)]
. Now create you own memory management scheme that uses that pool of memory with placement new. When that area is exhausted, create another pool. This has the effect of reducing the number of times the standardnew
operator needs to be called - thus reducing overhead. Ok, you have to manage each pool but working with fixed sized objects within each pool should be fairly efficient to to. There is a book called "Efficient C++" which looks at these issues in some detail. Hope this helps PhilYes, I had thought about allocating a couple of extra places and then when they are filled grabbing a new block and copying the contents in, which is essentially what realloc utilises. This is definitely one option, and is probably the way that the vector class works (in fact you can define its growth factor). However, I was hoping to come up with a nice tight memory usage, that makes things easy to use. The idea of placement new seems like what I want, 'use this memory address to initialise with this item'. I don't think it actually allocates any memory see, just initialises it with the item you supply. As you stated, I'd then have to whip through the array and call the destructor for each object manually, but this can be arranged :). If realloc needed a new memory block, the contents of my already initialise data would be copied in - no destructor is called, which is great because it were, when the array class destructor was called it would delete the same objects again :). I think I may be on the right lines, just waiting for someone to prove otherwise :). Thanks for your comments though Phil, they were very encouraging, which is something I need at the minute cos I've been on this a little while :). Many Thanks, Alan.
-
Thanks again Phil, I'm pretty sure alignment won't be a problem because malloc handles the correct alignment for buffers depending on their size (it doesn't matter exactly what object they are, only the size of the object will determine whether malloc has to pad the memory with x bytes to align it :)). Cheers for that article mind, very helpful explanation of placement new, which is new :) to me myself. Thanks again for your help Phil, much appreciated, Alan.
-
Yes, I had thought about allocating a couple of extra places and then when they are filled grabbing a new block and copying the contents in, which is essentially what realloc utilises. This is definitely one option, and is probably the way that the vector class works (in fact you can define its growth factor). However, I was hoping to come up with a nice tight memory usage, that makes things easy to use. The idea of placement new seems like what I want, 'use this memory address to initialise with this item'. I don't think it actually allocates any memory see, just initialises it with the item you supply. As you stated, I'd then have to whip through the array and call the destructor for each object manually, but this can be arranged :). If realloc needed a new memory block, the contents of my already initialise data would be copied in - no destructor is called, which is great because it were, when the array class destructor was called it would delete the same objects again :). I think I may be on the right lines, just waiting for someone to prove otherwise :). Thanks for your comments though Phil, they were very encouraging, which is something I need at the minute cos I've been on this a little while :). Many Thanks, Alan.
Alan, You shouldn't need to perform any copying. The idea of creating a memory block/pool that is several times larger than the object(s) you want to place within it is to reduce the number of times malloc or new are called (not placement new). When you have filled that block, allocate another and start using that one (you will now have two blocks containing object - there should be no need to copy the contents of your original block to the second one). Keep doing this for as long as you need space to store your objects. A scheme such as a two-way linked list that forms a header at the top of each block will enable you to keep track of each one allocated - and provide a mechansim to remove blocks once all the objects it contains are deleted. This should still be fairly efficient. Actually, I'm pretty sure this is how vector is implemented and I think the growth factor effectively determines the block/pool size used. Cheers, Phil
-
Alan, You shouldn't need to perform any copying. The idea of creating a memory block/pool that is several times larger than the object(s) you want to place within it is to reduce the number of times malloc or new are called (not placement new). When you have filled that block, allocate another and start using that one (you will now have two blocks containing object - there should be no need to copy the contents of your original block to the second one). Keep doing this for as long as you need space to store your objects. A scheme such as a two-way linked list that forms a header at the top of each block will enable you to keep track of each one allocated - and provide a mechansim to remove blocks once all the objects it contains are deleted. This should still be fairly efficient. Actually, I'm pretty sure this is how vector is implemented and I think the growth factor effectively determines the block/pool size used. Cheers, Phil
Yeah I see what your saying, its just because I'm creating a template container class for arrays of objects (I've already done one for linked lists), so I didn't really want to mess with having multiple new'd pointers (I wanted to be able to use pointer addition :)). Your right about the vector implementation, but I'm looking for a way of manipulating one contigous block of memory. I had thought of reserving larger chunks, and your solution of reserving another chunk is smart, but I'd like to see how much I can squeeze out one contigous memory block before I opt for plan B. :) Alan.
-
Hi all, back with a slightly different issue. OK, here's what I'm trying to do: I'm writing a template container class for a dynamic array (similar to the vector class). The class will be used as a basis for my own custom string allocation and more complex class structures. With this in mind, operator new in its standard form has not been implemented because it cannot be used to expand memory, I would, in effect, have to new another block of memory and copy the contents over before deleting the old block, this is slow and prone to mistakes. Therefore malloc has been implemented, with realloc, to handle the actual memory allocations. However, the problem with malloc is that it never calls the constructor for the object you want to store, it just allocates raw bytes. BUT, does this mean I could use placement new to initialise a block of memory with type T as follows:
T* p = malloc(sizeof(T)); if(p) { new (p) T; }
I would like to be able to call the constructor for each object in the malloc'ated area but similarly I can't use new cos I want it to be fast AND dynamic. Any good links, ideas, suggestions on how I'm going about this would be very much appreciated. This class will be a foundation for many things and I need it to be neat, at the moment it works, but its buggy cos things aren't getting constructed properly. Thanks guys.I'm not sure realloc will be more efficient than doing another new and copying. That's what realloc does beneath the surface, anyway. You only literally 'expand' an allocated space with realloc on those rare occasions where you have not done any other memory allocations since you malloc'd the memory you are expanding. I'd look into how efficient you can get the STL using custom allocator classes before you go as far as reimplementing a string class.
-
I'm not sure realloc will be more efficient than doing another new and copying. That's what realloc does beneath the surface, anyway. You only literally 'expand' an allocated space with realloc on those rare occasions where you have not done any other memory allocations since you malloc'd the memory you are expanding. I'd look into how efficient you can get the STL using custom allocator classes before you go as far as reimplementing a string class.
I think realloc will be faster when it comes to large objects because it will merely allocate a larger block of memory and copy the contents over - no destructors or constructors are called, therefore everything is A1. Also, new does have extra overhead because of the try,throw,catch implementation. However, using new/delete I'd have to reserve another memory block, but how pray do I move the objects into the new array? If I merely copy the bytes across, when I free up the previous allocation the objects destructor is called and so, those objects in the new array are total garbage (and they will get deleted again the next time a reallocation is made. Nasty. Any ideas on how to get around that would be very useful, and I would definitely use that method instead :). Cheers, Alan.