New type-based pool allocator code miscompiled due to aliasing issue?

Martin Jambor mjambor@suse.cz
Wed Jun 17 09:18:00 GMT 2015


Hi,

On Tue, Jun 16, 2015 at 05:31:57PM +0200, Martin Liska wrote:
> On 06/16/2015 04:02 PM, Richard Biener wrote:
> > On Tue, Jun 16, 2015 at 3:38 PM, Martin Liška <mliska@suse.cz> wrote:

...

> >> Do you mean Richard following changes:
> >>
> >> alloc-pool.h (allocate):
> >> ...
> >> +  /* Placement new contructor.  */
> >> +  inline void *operator new (size_t, elt_loc_list *&ptr)
> >> +  {
> >> +    return ptr;
> >> +  }
> > 
> > That should be there with including <new>
> > 
> >> and e.g. cselib.h:
> >>
> >> struct cselib_val
> >> {
> >>   /* Pool allocation new operator.  */
> >>   inline void *operator new (size_t)
> >>   {
> >>     return pool.allocate ();
> >>   }
> >>
> >>   /* Placement new contructor.  */
> >>   inline void *operator new (size_t, char *&ptr)
> >>   {
> >>     return ptr;
> >>   }
> > 
> > Yes, though I wonder whether cselib_val should really have undefined
> > contents after
> > allocating it?  (or does the pool allocator zero the memory?)
> > 
> > Richard.
> 
> Hio.
> 
> I've added calling of placement new operators and memset a memory, look the patch
> works for me.
> 
> If it's the right way, I'll write Changelog and run testsuite.

So do I understand this thread correctly that any clas that overrides
its new operator to allocate from a pool also has to override its
placement new operator (to just return the argument)?  (I'm thinking
of doing the same in the HSA branch.) If so, I think it would warrant
at least a simple comment before the pool allocator class in
alloc-pool.h.


> From d60bc8fa02161df64ddbb6bdb35c733af5e073c6 Mon Sep 17 00:00:00 2001
> From: mliska <mliska@suse.cz>
> Date: Tue, 16 Jun 2015 17:28:27 +0200
> Subject: [PATCH] Add placement new for classes in pool allocator.
> 
> ---
>  gcc/alloc-pool.h   | 10 +++++++++-
>  gcc/asan.c         |  6 ++++++
>  gcc/cselib.c       |  6 ++++++
>  gcc/cselib.h       | 15 +++++++++++++++
>  gcc/dse.c          | 30 ++++++++++++++++++++++++++++++
>  gcc/et-forest.c    |  6 ++++++
>  gcc/et-forest.h    |  8 ++++++++
>  gcc/ira-color.c    |  6 ++++++
>  gcc/lra-int.h      | 18 ++++++++++++++++++
>  gcc/regcprop.c     |  6 ++++++
>  gcc/tree-sra.c     | 12 ++++++++++++
>  gcc/var-tracking.c | 21 +++++++++++++++++++++
>  12 files changed, 143 insertions(+), 1 deletion(-)
> 
> diff --git a/gcc/alloc-pool.h b/gcc/alloc-pool.h
> index 1785df5..237ece3 100644
> --- a/gcc/alloc-pool.h
> +++ b/gcc/alloc-pool.h
> @@ -413,7 +413,15 @@ pool_allocator<T>::allocate ()
>    VALGRIND_DISCARD (VALGRIND_MAKE_MEM_UNDEFINED (header, size));
>  
>    /* Call default constructor.  */
> -  return (T *)(header);
> +  T *ptr = (T *)header;
> +
> +  if (!m_ignore_type_size)
> +    {
> +      memset (header, 0, sizeof (T));
> +      return new (ptr) T ();
> +    }
> +  else
> +    return ptr;
>  }

Interesting, does this mean that the allocator will clear the memory
for all types?  I thought the initialization of data should be left to
the class itself and its constructor.  On the other hand, I suppose
that memset(this, 0, sizeof(*this)) is a very bad idea in C++, so the
simplicity of this might actually justify the overhead in cases where
we don't need the zeroing.

Thanks,

Martin



More information about the Gcc-patches mailing list