On 11/22/2010 04:41 PM, Alberto Griggio wrote: > Hello, > I'm having trouble understanding what I'm doing wrong in the following piece > of code. > > My OS is Debian GNU/Linux 5.0, compiler is > g++-4.1 (GCC) 4.1.3 20080704 (prerelease) (Debian 4.1.2-25) > platform x86-64 > > The following code results in abort() being called (sorry if it's a bit > long, but this is the smallest example I could come up with): > > #include <new> > #include <stdlib.h> > #include <assert.h> > #include <stdio.h> > > struct Link { Link *next_; }; // __attribute__((__may_alias__)); > struct Foo { void *value; }; > > struct Alloc { > Alloc() { head_ = NULL; } > ~Alloc() {} > > void *allocate() > { > static int cnt = 0; > if (head_ == NULL) { > if (cnt++) { abort(); } > > Link *mem = static_cast<Link *>(malloc(sizeof(Link) * 3)); > head_ = new (mem) Link; > Link *last = head_ + 2; > for (Link *p = head_; p < last; ++p) { > Link *next = new (p+1) Link; > p->next_ = next; > } > last->next_ = NULL; > } > Link *p = head_; > head_ = p->next_; > p->~Link(); > return static_cast<void *>(p); > } > > Link *head_; > }; > > struct FooAlloc { > Foo *alloc() { return new (p_.allocate()) Foo(); } > Alloc p_; > }; > > int main() > { > if (sizeof(Foo) != sizeof(Link)) { abort(); } > printf("here\n"); fflush(stdout); > > FooAlloc pool; > Foo *e = pool.alloc(); > if (e) { > printf("e\n"); fflush(stdout); > } > e = pool.alloc(); > return 0; > } > > > If I uncomment the "may_alias" attribute, everything works. But I don't > quite understand why "may_alias" is needed here. Could somebody help please? > My understanding is that, since in Alloc::allocate() I'm calling the > destructor of p before returning a pointer to the memory in which it is > allocated, and in FooAllo::alloc() I'm constructing a new object in that > memory area, aliasing should not be an issue. It's much simpler than that. Here you have a Link* : Link *p = head_; head_ = p->next_; p->~Link(); return static_cast<void *>(p); and you cast it to a Foo* : Foo *e = pool.alloc(); Foo and Link are not compatible types. You cannnot take a pointer to a Link and alias it to a pointer to a Foo. Your problem is these two casts. gcc doesn't spot the problem because you're going via void*. Andrew.