MemoryPool Class from Efficient C++ Failing

H

Hanzo

I'm currently fighting my way through an example of Single-Threaded
Memory Pooling in a chapter of the Efficient C++ book by Dov Bulka &
David Mayhew. Unfortuantely, I'm starting to get code that won't
compile and I am having a hard time finding an online errata or
contacting the authors.

For those familiar with the book, Chapter 6 covers rolling your own
memory manager. The first section, dealing with a Specialized Rational
Memory Manager (Rational is a custom class to handle fractions)
compiles fine, however the next sections fail. The first of these
sections is the Fixed-Size Object Memory Pool. The code, line for
line, reads at the end of this post.

My compile errors are with the lines referring to static_cast, saying
"Cannot convert from 'char *' to 'class MemoryPool<class Rational>*'.

I'd love to be able to figure this out, but sadly, that's why I'm
reading the book; I am not sure how this is failing. Any help would be
appreciated.

- Hanzo

=========

template<class T>
class MemoryPool
{
public:
MemoryPool(size_t size = EXPANSION_SIZE) {
expandTheFreeList(size); }
~MemoryPool();

// Allocate a T element from the free list
inline void *alloc(size_t size);

// Return a T element to the firee list
inline void free(void *someElement);
private:
// next element on the free list.
MemoryPool<T> *next;

// if the freeList is empty, expand it by this amount
enum { EXPANSION_SIZE = 32 };

// add free elements to the free list
void expandTheFreeList(int howMany = EXPANSION_SIZE);
};

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

template<class T>
inline void* MemoryPool<T>::alloc(size_t size)
{
if (!next)
expandTheFreeList();

MemoryPool<T> *head = next;
next = head->next;

return head;
}

template<class T>
inline void MemoryPool<T>::free(void *doomed)
{
MemoryPool<T> *head = static_cast<MemoryPool<T>*>(doomed);

head->next = next;
next = head;
}

template<class T>
void MemoryPool<T>::expandTheFreeList(int howMany)
{
// We must allocate an object large enough to contain the
// next pointer
size_t size = (sizeof(T) > sizeof(MemoryPool<T>*)) ? sizeof(T)
: sizeof(MemoryPool<T>*);

MemoryPool<T> *runner = static_cast<MemoryPool<T>*>(new
char[size]);

next = runner;

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

runner->next = NULL;
}

// ===========================

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;
};

MemoryPool<Rational> *Rational::memPool = NULL;

int main()
{
Rational *array[1000];

Rational::newMemPool();

int start = timeGetTime();

for (int j=0; j<1; j++)
{
for (int i=0; i<1; i++)
{
array = new Rational(i);
}
for (i=0; i<1; i++)
{
delete array;
}
}

int end = timeGetTime();

Rational::deleteMemPool();

cout << "The time was " << end-start << endl;

return 0;
}
 
D

David B. Held

Hanzo said:
[...]
My compile errors are with the lines referring to static_cast,
saying "Cannot convert from 'char *' to 'class
MemoryPool<class Rational>*'.
[...]

Usually, it's most polite to indicate the lines with the errors
in the posted code. That way, readers don't have to scan
through what may be hundreds of lines of unrelated code
just looking for the erroneous line.
[...]
MemoryPool<T> *runner = static_cast<MemoryPool<T>*>(new
char[size]);

I assume this is one of the lines that is giving you problems?
The problem is that there is no valid conversion from char*
to MemoryPool<T>*, just like the error says. So you need to
use an intermediate conversion to void*, like so:

MemoryPool<T> *runner =
static_cast<MemoryPool<T>*>(
static_cast<void*>(new char[size])
);

See if that works, and don't forget to fix the other occurence.

Dave
 
H

Hanzo

Usually, it's most polite to indicate the lines with the errors
in the posted code. That way, readers don't have to scan
through what may be hundreds of lines of unrelated code
just looking for the erroneous line.

Sorry, I can never get that right. Sometimes I post a fragment and
then everyone wants to see more code. :)
MemoryPool<T> *runner =
static_cast<MemoryPool<T>*>(
static_cast<void*>(new char[size])
);

See if that works, and don't forget to fix the other occurence.

That definitely did work, thanks. However, there is still a problem in
execution, which I believe is tied to the line:

delete [] nextPtr;

in the destructor of MemoryPool<T>. Although that is line for line
what it has in the book (which have already proven wrong), is it
possible that the form of delete, as it seems fine with the array []
designation, should it be cast into some other type before the delete?

I dunno. I am just guessing here.

- Hanzo
 
D

David B. Held

Hanzo said:
[...]
That definitely did work, thanks. However, there is still a problem
in execution, which I believe is tied to the line:

delete [] nextPtr;

Unlikely, since you are allocating your blocks with new char[...].
[...]
I dunno. I am just guessing here.

State what the actual erroneous output is, along with what you
think it should be, so I don't have to compile the code myself.
Help me help you. ;)

Dave
 
H

Hanzo

State what the actual erroneous output is, along with what you
think it should be, so I don't have to compile the code myself.
Help me help you. ;)

On the line:

delete [] nextPtr;

I set a breakpoint. I execute to that line, and if I make one more
step, I get a general protection fault.

User breakpoint called from code at 0x77f75a58.

If I change it to this:

void* ptr = static_cast<void*>(nextPtr);
delete [] ptr;

The code executes without error. Now, whether or not i have a memory
leak is a different story.

- Hanzo
 

Ask a Question

Want to reply to this thread or ask your own question?

You'll need to choose a username for the site, which only take a couple of moments. After that, you can post your question and our members will help you out.

Ask a Question

Members online

Forum statistics

Threads
473,777
Messages
2,569,604
Members
45,218
Latest member
JolieDenha

Latest Threads

Top