By using this site, you agree to our updated Privacy Policy and our Terms of Use. Manage your Cookies Settings.
449,149 Members | 1,037 Online
Bytes IT Community
+ Ask a Question
Need help? Post your question and get tips & solutions from a community of 449,149 IT Pros & Developers. It's quick & easy.

Custom Allocator Question - Advanced.

P: n/a
joe
I have written a custom std allocator which follows the example in
Stroustrup's book.

I'm seeing a behavior I don't understand.

My allocate method within the allocator looks like the following:
(FooAllocator<T>)

pointer allocate(size_type cnt, typename
std::allocator<void>::const_pointer hint = 0)
{
pointer p = reinterpret_cast<pointer(new char[sizeof(T)*cnt]);
std::cout<<"MEMORY ADDRESS: "<<p<<std::endl; //FIRST PRINT-OUT!
return p;
}

Then I have a regular container in my main:
int main()
{
typedef std::multiset<Foo,less<Foo>,FooAllocator<Foo MYSET;

MYSET mine;

MYSET::iterator iter = mine.insert(Foo());
std::cout<<"ITER = "<<&(*iter)<<std::endl;
}

The address of the iterator being returned is 16 Bytes graeter than
the address of the allocated memory. This is true in multiple
compilers, and is causing me to overwrite the end of my allocated
memory. It doesn't seem to matter what type of object Foo is.

has anyone seen this before or have any ideas?
Thanks,
Joe

May 23 '07 #1
Share this Question
Share on Google+
3 Replies


P: n/a
joe wrote:
I have written a custom std allocator which follows the example in
Stroustrup's book.

I'm seeing a behavior I don't understand.

My allocate method within the allocator looks like the following:
(FooAllocator<T>)

pointer allocate(size_type cnt, typename
std::allocator<void>::const_pointer hint = 0)
{
pointer p = reinterpret_cast<pointer(new char[sizeof(T)*cnt]);
This is probably the cause of your problem. reinterpret_cast is not a
safe cast and it does not guarantee proper object alignment.

F
std::cout<<"MEMORY ADDRESS: "<<p<<std::endl; //FIRST PRINT-OUT!
return p;
}

Then I have a regular container in my main:
int main()
{
typedef std::multiset<Foo,less<Foo>,FooAllocator<Foo MYSET;

MYSET mine;

MYSET::iterator iter = mine.insert(Foo());
std::cout<<"ITER = "<<&(*iter)<<std::endl;
}

The address of the iterator being returned is 16 Bytes graeter than
the address of the allocated memory. This is true in multiple
compilers, and is causing me to overwrite the end of my allocated
memory. It doesn't seem to matter what type of object Foo is.

has anyone seen this before or have any ideas?
Thanks,
Joe
May 23 '07 #2

P: n/a
joe wrote:
pointer allocate(size_type cnt, typename
std::allocator<void>::const_pointer hint = 0)
{
pointer p = reinterpret_cast<pointer(new char[sizeof(T)*cnt]);
std::cout<<"MEMORY ADDRESS: "<<p<<std::endl; //FIRST PRINT-OUT!
return p;
}
Just for fun change the log message to this:
std::cout <<"MEMORY ADDRESS: " << p << ", sizeof T is"
<< sizeof(T) << std::endl;
Then I have a regular container in my main:
int main()
{
typedef std::multiset<Foo,less<Foo>,FooAllocator<Foo MYSET;

MYSET mine;

MYSET::iterator iter = mine.insert(Foo());
std::cout<<"ITER = "<<&(*iter)<<std::endl;
}

The address of the iterator being returned is 16 Bytes graeter than
the address of the allocated memory. This is true in multiple
compilers, and is causing me to overwrite the end of my allocated
memory. It doesn't seem to matter what type of object Foo is.
&(*iter) is not the address of the iterator, it's the address of the
object "pointed" to by the iterator. As you can see, the object has a
different address to one you returned from the allocate call. This may
be because the instance of the allocator template that is being used is
probably not the one you think is being used.

Presumably you had to define a rebind struct, can you see what has happened?

If not, add some logging to your constructors, especially the templated one.
template<class UFooAllocator(const FooAllocator<U>&)

Charles.
May 23 '07 #3

P: n/a
On May 23, 9:46 pm, joe <joeyc...@mail.comwrote:
I have written a custom std allocator which follows the example in
Stroustrup's book.
I'm seeing a behavior I don't understand.
My allocate method within the allocator looks like the following:
(FooAllocator<T>)
pointer allocate(size_type cnt, typename
std::allocator<void>::const_pointer hint = 0)
{
pointer p = reinterpret_cast<pointer(new char[sizeof(T)*cnt]);
std::cout<<"MEMORY ADDRESS: "<<p<<std::endl; //FIRST PRINT-OUT!
return p;
}
Then I have a regular container in my main:
int main()
{
typedef std::multiset<Foo,less<Foo>,FooAllocator<Foo MYSET;
MYSET mine;
MYSET::iterator iter = mine.insert(Foo());
std::cout<<"ITER = "<<&(*iter)<<std::endl;
}
The address of the iterator being returned is 16 Bytes graeter than
the address of the allocated memory. This is true in multiple
compilers, and is causing me to overwrite the end of my allocated
memory. It doesn't seem to matter what type of object Foo is.
Presumably (I don't see how one could implement it differently),
what is being allocated in the multiset is not a T, but some
sort of node structure containing a T, typically with a couple
of pointers before the T. And the actual type of the allocator
being used to do the allocation should not be T, but this node
type.

Having said this, I don't quite see how this could be causing
you to overwrite anything. The allocation expression should be
something like (typedef's expanded, etc.):

__Alloc::rebind<__Node>::other( myAlloc ).allocate( n )

If you're rebind declaration is correct, and the code for
allocate is really what you show, then you should have no
trouble in this respect; if you're not sure, add output of
typeid(T).name and sizeof(T) to your allocator, to see what is
going on.

--
James Kanze (GABI Software) email:ja*********@gmail.com
Conseils en informatique orientée objet/
Beratung in objektorientierter Datenverarbeitung
9 place Sémard, 78210 St.-Cyr-l'École, France, +33 (0)1 30 23 00 34

May 24 '07 #4

This discussion thread is closed

Replies have been disabled for this discussion.