Sign in to follow this  

Is it possible to use new to allocate adjacent blocks of memory?

This topic is 3294 days old which is more than the 365 day threshold we allow for new replies. Please post a new topic.

If you intended to correct an error in the post then please contact us.

Recommended Posts

Hi, I have a class which upon construction creates a specified number of objects of another class using new CObject...etc. I was just wondering if it is possible to have each new command allocate memory adjacent to the block previously allocated. My current thinking is that the only way to do this would be to allocate a large block of memory and then allocate the objects within this large block. Just a guess though! Thanks

Share this post


Link to post
Share on other sites
Factory Pattern with Placement New (1, 2, 3) is probably what you are looking for.

You can create a chunk of memory and then use a list to keep track of what in the chunk is available. Have a list for both 'new' and 'used' memory. When an object is deleted/released back to the factory, ensure it is in the used list (to catch bad releases), deconstruct the object, and put the memory back in the free list.

When the factory is being deconstructed, make sure all the memory is in the free list. Then you can free the entire block.


EDIT: I just realized I wrote a journal post about this a lonnngggg time ago. A bit old, but you can look at some of my code here (look at entry for June 19th). I have a full listing of code in the comments of another journal, which can be found here. You might want to read this post to understand some of the design decisions. Please note that the code is VERY OLD and does not necessarily represent what I feel are good design decisions anymore. But you might be able to rip the placement new stuff out.

[Edited by - visage on December 8, 2008 5:18:47 AM]

Share this post


Link to post
Share on other sites
Are you sure you need to be using a linked list?
I've been trying to find a good reference which explains the trade offs between different collection types, but haven't had much success (anybody know any good links?).
Anyway if you have to use a linked list, and are doing alot of insertion and deletion (otherwise why use a linked list?), then you are not going to be able to keep memory usage contiguous (in a single block), without doing alot of reallocation and copying. In that case you may aswell just use an std::vector.

Share this post


Link to post
Share on other sites
Ok thanks guys, I've been looking at placement new and I now have an array of objects that I allocatoe like so:


//Class property
CObject< Type >* m_Data;

//...in constructor
m_Data = new CObject< Type >[Size];


Thing is when I do it this way it's throwing up a linker error LNK2001.
Strange because if I do it with a base type (like int) it works fine.

p.s. the CObject template class DOES have a default constructor...

Share this post


Link to post
Share on other sites
Quote:
Original post by DOrmisher
Ok thanks guys, I've been looking at placement new and I now have an array of objects that I allocatoe like so:


//Class property
CObject< Type >* m_Data;

//...in constructor
m_Data = new CObject< Type >[Size];


Thing is when I do it this way it's throwing up a linker error LNK2001.
Strange because if I do it with a base type (like int) it works fine.

p.s. the CObject template class DOES have a default constructor...


The parameter type you are using may be missing a default constructor; I assume you are creating an instance of 'Type' somewhere in CObject<Type>.

Share this post


Link to post
Share on other sites
My little test code of your problem works fine:

#include "stdafx.h"

template < class T >
class CObject
{
T* tptr;

public:
CObject() : tptr(NULL) {}
};

template < class T >
class TestClass
{
CObject < T >* obs;

public:
TestClass ()
{
obs = new CObject < T > [5];
}

~TestClass()
{
delete[] obs;
}
};

int _tmain(int argc, _TCHAR* argv[])
{
TestClass<int> tclass;

return 0;
}




What are you doing that is different from that?

P.S what you mention is not placement new, just the array version of new. Placement new constructs an object at a location in memory that has been previously allocated and looks like:


void* place = operator new(sizeof(Something));
Something* p = new (place) Something();




/edit
oops too slow!

Share this post


Link to post
Share on other sites
Quote:
Original post by DOrmisher
Well type is a template type. But no worries anyway the problem was with my CObject destructor...problem sorted.

Thanks


Ya it is obviously a template type :). I just meant that you could be creating one when you created the template class, if I had of looked at the original post more carefully i would have seen that you do not, doh :)

Share this post


Link to post
Share on other sites
Ah so that isn't placement new?? What about if I do it like this...

m_Data = operator new (sizeof (CObject< Type >[ Size ]) );

//and then when allocating memory...
obj = new (m_Data) CObject< Type >();


Thing is if I do it this way, every time I allocate a a new obj to the block of memory like above. Will it not just overwrite the previous allocation?

Share this post


Link to post
Share on other sites
Quote:
Original post by DOrmisher
I was just wondering if it is possible to have each new command allocate memory adjacent to the block previously allocated.


No (for non-placement new), because (a) the concept of "adjacent" is already blurred by the OS, and (b) that memory might not be available.

Quote:
My current thinking is that the only way to do this would be to allocate a large block of memory and then allocate the objects within this large block. Just a guess though!


Which is basically what std::vector does; except that it also has enough smarts to start out with a smallish block and (periodically, as the need is proven) re-allocate a larger block and move (by copying and then destroying the original) elements to there, then deallocate the smaller block.

Quote:
Well I'm using a linked list


If this is a linked list you made yourself, and the only reason you're using it is because it's the only way you know to manage an unknown-ahead-of-time-sized collection, then you need to re-educate yourself.

If not, you should be aware that simply allocating each new node in sequential memory offers little performance benefit, while forcing the elements to appear sequentially in memory defeats the purpose of using a linked list (as opposed to, say a vector) entirely.

In any case, my recommendation is to just try std::vector<T>, remove any logic you might have for maintaining an "internal" linked list, and see how that works for you. Placement new is tricky business that you shouldn't have to worry about yourself. If 'CObject' (and WTF is a cobject, anyway?) is a polymorphic base class, you will probably instead want to use boost::ptr_vector, or a vector of some kind of smart pointer class, instead. (But the same is true if you were using std::list.)

Share this post


Link to post
Share on other sites

This topic is 3294 days old which is more than the 365 day threshold we allow for new replies. Please post a new topic.

If you intended to correct an error in the post then please contact us.

Create an account or sign in to comment

You need to be a member in order to leave a comment

Create an account

Sign up for a new account in our community. It's easy!

Register a new account

Sign in

Already have an account? Sign in here.

Sign In Now

Sign in to follow this