Hi,

I would like to reopen the discussion for pr/15795, or at least get
clarification on the current resolution of WONTFIX.
http://gcc.gnu.org/bugzilla/show_bug.cgi?id=15795

Let me state right at the beginning that I am also volunteering to do
the actual work to come up with an agreed solution and implement it.

Briefly, pr/15795 was submitted to address the issue of calling the new
operator for a class which has an alignment greater than that guaranteed
by the underlying malloc().  It specifically talks about alignment for
vector types, but it applies to any alignment.

For example, a 16 byte vector type typically requires 16 byte alignment
and malloc() might only guarantee 8 byte alignment.  When a class
contains that vector the class requires alignment of 16, but a new
operator that calls that malloc() will not always return properly
aligned memory.

The pr proposes some solutions:

  solution:  operator new should always return 16 byte aligned memory
  response:  glibc doesn't do that, neither should libstdc++

    I agree with this response.  A solution that handles any alignment
    is better, simply changing the default isn't sufficient.

  solution:  create an additional signature for operator new which
             has a parameter that indicates the alignment.  The compiler
             should call this version of the operator when necessary and
             the standard library should provide an appropriate
             implementation.
  response:  "would interact badly with overriding the default operator
             new."

    At first glance, this could break some existing code, but I think
    this solution could be made to work.  I'll discuss below.

  solution:  the library will provide an implementation of a new operator
             with an additional parameter, but the user is responsible for
             calling it.
  response:  doesn't work well with existing template class libraries,
             like STL or Qt.

    I agree with this response.  (There was no agreement or disagreement
    with this response in the pr.)

For the second proposed solution, let's define precisely the cases that
"interact badly".  I can think of only one case, defined by these
conditions:
  - a type has an alignment greater than what malloc() guarantees
  - operator new for that type does not call the default implementation
    for operator new
  - an object of that type is created using operator new
  - an appropriate implementation of operator new with the additional
    alignment parameter is not provided for this type.
 
Clearly, if the compiler does not call the user defined version of
operator new in this case, the code is likely to break.  Are there
other cases which "interact badly"?

I'm hoping a solution to this case is as simple as:
  - when the compiler would call the aligned version of operator new it
    first checks which definition of operator new would have been called
    if it were not aligned.  If there is an aligned version of operator
    new in the same place*, call it, otherwise call the non-aligned
    version and issue a warning.  (* for "place" fill in the appropriate
    C++ jargon for it to make sense, e.g., namespace, class, scope.)
  - the default versions of operator new and the aligned version of
    operator new should be defined in the same section.  That way,
    when a user overrides the default operator new, they will get
    a link error (duplicate definitions of new) unless they also
    define the aligned version of operator new.

Can anyone identify situations where this wouldn't work?  In the
case where it generates a warning the code might not work because
of improper alignment, but at that point I would consider it the
users problem.

While I'm here let me also point out that an object which is allocated
on the stack and has alignment greater than what the stack guarantees is
also an issue.  I have a patch which fixes this for any alignment,
though it doesn't take advantage of stack ordering.  

Thanks,
Trevor

Reply via email to