MemoryHandler class

Started by
4 comments, last by angry 20 years, 6 months ago
I'm making a memory handler class which will handle well all the memory used in my programs. However I am a bit uncertain of how to do this the best and fastest way. The way I've been doing so far is by basically allocating a huge array of unsigned char's in the beginning of the program and then let my objects retrieve their memory from it. This is how the code looks like at the moment, there are still a couple of things i need to implement like concatenating of unused small proptions of memory and dynamic memory allocation when the "static" memory is out of memory, etc... Why I ask this question now is just to know if I should continue with what im doing or quit and do something else



// the size of the MemBlockInfo structure (5 bytes)

#define MEMBLOCKINFO_SIZE	5	

// this structure is what is before every memory block. this structrure

// holds information about the size of the memory block and if it's

// used or not..

struct MemBlockInfo
{
	UInt32	size;		// the size of the memory block

	UInt8	flag;		// is memory used or not?

};


// this method scans it's static and dynamic memory for a free slot

// that can hold <size> amount of memory. If it succeeds it returns

// a pointer to the beginning of that memory, otherwise it returns NULL.


// some notes

// UInt8* staticMemory;   

// UInt32 staticMemorySize;

Void* MemoryManager::getMemory(UInt32 size)
{
	// don't scan for memory if size is 0

	if(size == 0) return NULL;
				
	MemBlockInfo*	memBlockInfo;
	MemBlockInfo*	memBlockInfo2;
	for(UInt32 address=0; address<staticMemorySize; address++)
	{
		// retrieve the memory block information which is always before

		// the actual allocated memory...

		memBlockInfo = reinterpret_cast<MemBlockInfo*>(&staticMemory[address]);
			
		// check if the we've encountered unused memory, this is most likley

		// to occure in the beginning of a program when the first memory are

		// allocated...

		if(memBlockInfo->size == 0)
		{
			// we can reserve any amount of memory as long as it

			// stays inside the static memorys boundaries. Otherwise

			// we have to allocate it at the dynamic memory...

			if((address+size+MEMBLOCKINFO_SIZE) > staticMemorySize)
				return NULL; // dynamic memory not implemented yet

							
			memBlockInfo->size = size;
			memBlockInfo->flag = 1;
			return reinterpret_cast<Void*>(&staticMemory[address+MEMBLOCKINFO_SIZE]);
		}
					
		// check if we've encountered memory that has equal or greater

		// size than what we want and that it is unused...

		if(memBlockInfo->size >= size && memBlockInfo->flag != 1)
		{
			// check if this memory block is much larger than what we

			// need. if it is, try to divide the block into two seperate

			// parts...

			if(memBlockInfo->size > (size+MEMBLOCKINFO_SIZE))
			{
				memBlockInfo2 		= reinterpret_cast<MemBlockInfo*>(&staticMemory[address+MEMBLOCKINFO_SIZE+size]);
				memBlockInfo2->size	= memBlockInfo->size-size;
				memBlockInfo2->flag	= 0;
				memBlockInfo->size	= size;
			}
						
			memBlockInfo->flag = 1;
			return reinterpret_cast<Void*>(&staticMemory[address+MEMBLOCKINFO_SIZE]);
		}
					
		address+=MEMBLOCKINFO_SIZE+memBlockInfo->size-1;					
	}
				
	return NULL;
}

// example of how a program using this memory handler could look like

int main(int, char**)
{
	MemoryManager* mem = MemoryManager::getInstance();
	
	int* x  = reinterpret_cast<int*>(mem->getMemory(sizeof(int)));
	*x 	= 10;

	std::cout << *x << std::endl;
	std::cin.ignore();
	MemoryManager::freeInstance();
	return 0;
}
Just to clearify how memory is stored and the memory block information:


|<---5bytes--->|       
------------------------------------------------
| MemBlockInfo | Memory | MemBlockInfo | Memory|
------------------------------------------------

// Where Memory is as large as said in the first four bytes of MemBlockInfo.
  
Is this the way to go? Or should I just make it simple and just set up a list of pointers to all objects that are created during execution and then delete them all... And hows about speed issues? The problem with speed I can see is that the more memory that is allocated, the more if statements it has to run to find free memory. [edited by - angry on October 9, 2003 6:35:05 PM] [edited by - angry on October 9, 2003 6:41:53 PM] [edited by - angry on October 10, 2003 4:55:33 AM]
Advertisement
I don''t really have time to answer any of your questions, but I did scan your code and your assumming that the size of MemBlockInfo is always 5, which might not always be true (some compilers might add padding to the structure so that its size is a power of two). A better way to define that would be like this:
#define MEMBLOCKINFO_SIZE sizeof(MemBlockInfo)
Or just skip the define entirely and just use sizeof.

I know that, however the real size of the structure isn''t important.
Are you doing this for performance reasons? If so, why not just pre-allocate at startup time of pool of objects for the classes that are instantiated the most? You can either write a manager class or (I think, though I''ve never done it this way) overload the new operator for your class.

--
Dave Mikesell
d.mikesell@computer.org
http://davemikesell.com
Im doing it both for performance and to make my library safe from memory leaks etc...

I''ve thought of just creating a class which contains pointers to all objects that are created however, as I read about memory handling I discovered that it is a rather slow process and that fragmentation is very common and gets worse if you create a lot of small objects, which will be a common thing to happen in with my library. Also I read that new and delete is pretty slow operators which should not be used in a rendering loop for example. Of course I could use a pool of memory for those certain times but I like complicating things
I don''t know the specifics of your library, but re: memory leaks I find them difficult to encounter the way I program in C++: strings instead of char *, STL instead of homegrown containers, smart pointers instead of raw pointers, raw pointers (when necessary) managed by constructor/destructor.

Are your performance concerns warranted by profiling? i.e., is your code slow now and have you deemed that memory allocation/deallocation is the bottleneck?

I don''t mean to sound preachy or pedantic, but this seems like a lot of work!

--
Dave Mikesell
d.mikesell@computer.org
http://davemikesell.com

This topic is closed to new replies.

Advertisement