Runtime error in destructor of memory pool

In the following program, I got runtime error (program hangs) from template <typename T>
MemoryPool<T>::~MemoryPool(). I suspect that it has something to do with the reinterpret_cast that is used in the contructor. Can some one help by pointing out how to fix it? Thanks in advance.

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
template <typename T>
class MemoryPool 
{
public:
	MemoryPool( size_t in_size = EXPANSION_SIZE );
	~MemoryPool();

	inline void *alloc(size_t size);
	inline void free(void *doomed);

private:
	MemoryPool<T> *next;
	enum { EXPANSION_SIZE = 32 };
};

template <typename T>
MemoryPool<T>::MemoryPool( size_t in_size )
{
	size_t size = ( sizeof( MemoryPool<T>* ) > (sizeof(T) )) ? sizeof( MemoryPool<T>* ) : sizeof(T);
	MemoryPool<T> *runner = reinterpret_cast< MemoryPool<T>* > (new char[size]);

	next = runner;
	for (int i = 0; i < in_size; ++i) {
		runner->next = reinterpret_cast< MemoryPool<T>* > (new char[size]);
		runner = runner->next;
	}
	runner->next = 0;
}

template <typename T>
MemoryPool<T>::~MemoryPool()
{
	MemoryPool<T> *nextPtr;
	for (nextPtr = next; nextPtr != 0; nextPtr = next) {		
		next = next->next;
		delete [] nextPtr;
	}	
}




EDIT: sorry, I did not post complete program above (now two line methods added to it). Here is more of it (please note: it is still not a complete implementation, but should give an idea of the problem)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
class Rational 
{
public:
	Rational(int a = 0, int b = 1 ) :n(a), d(b) {}

        void *operator new(size_t size) { return memPool->alloc(size); }
	void operator delete(void *doomed, size_t size) { memPool->free(doomed); }

        static void newMemPool() { memPool = new MemoryPool<Rational>; }
	static void deleteMemPool() {  delete memPool; }		
		
private:
	int n;
	int d;
	static MemoryPool<Rational> *memPool;
}

int main() 
{	
	Rational::newMemPool();
	// .. other code

                // runtime error!
	Rational::deleteMemPool();
	
	return 0
}
Last edited on
Since you don't appear to be constructing the MemoryPool<T> objects (you are not calling their constructors), you cannot delete[] them using a pointer of that type. You must delete[] using a char pointer.
Change
delete [] nextPtr;
to
delete [] reinterpret_cast<char*>(nextPtr);

Otherwise it tries to delete array of MemoryPool<T> calling destructors for each object of the array. Meantime there is no array of MemoryPool<T>. It is array of char-s.

This code uses uninitialized objects. There is no placement new calls on allocated memories. Why don't you use std::list?
agile, thank you very much. Your suggestion works and your explanation makes perfect sense. Yes, I did not contruct the MemoryPool<T> objects so I can not delete [] nextPtr in the dtor. The code was taken from a book that I wanted to throw away because this code did not compile. Now I pick it up again.

The trickest thing in the book for me is the aftermentioned struct NextOnFreeList as another implementation of a memory pool. Its first few bytes are used as next pointer in a linked list. Yet it actually contains a list of Rational objects. In other words, the struct NextOnFreeList "have a dual role as a sequence of Rational objects as well as a sequence of NextOnFreeList element". I do not fully understand what is going on with the reinterpret_cast<> under the hood. Can some one help explain it?

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
struct NextOnFreeList {
	NextOnFreeList *next;	
};

class Rational
{
public:
	Rational(int a = 0, int b = 1);
	~Rational();

	inline void *operator new(size_t size);
        inline void operator delete(void *doomed, size_t size);

        static void newMemPool() { expandTheFreeList(); }
        static void deleteMemPool();	
							
private:
	static NextOnFreeList *freeList;	
        enum { EXPANSION_SIZE = 32 };
	int n;			
        int d;		
};

void Rational::expandTheFreeList()
{
	size_t size = ( sizeof(Rational) > sizeof(NextOnFreeList *) 
                                   ? sizeof(Rational) : sizeof(NextOnFreeList*) );

	NextOnFreeList *runner = reinterpret_cast<NextOnFreeList*> (new char[size]);
	
	freeList = runner;

	for (int i = 0; i < EXPANSION_SIZE; ++i) {
		runner->next = reinterpret_cast<NextOnFreeList *>(new char[size]);
                                runner = runner->next;
	}
	runner->next = 0;
}
Last edited on
Topic archived. No new replies allowed.