Stan1989 / owasp-esapi-cplusplus

Automatically exported from code.google.com/p/owasp-esapi-cplusplus
0 stars 0 forks source link

zAllocator compile issue on GCC 4.6 #11

Open GoogleCodeExporter opened 9 years ago

GoogleCodeExporter commented 9 years ago
On 18 August 2011 09:27, Jeffrey Walton <noloader@gmail.com> wrote:
> On Thu, Aug 18, 2011 at 4:21 AM, Jonathan Wakely <jwakely.gcc@gmail.com> 
wrote:
>> On 18 August 2011 08:55, Jeffrey Walton wrote:
>>> Hi Jonathan,
>>>
>>> Sorry to go offlist, but its off topic.
>>
>> This is a slightly trickier one.  The problem is in an incomplete
>> C++0x implementation in libstdc++ 4.6, but there's a simple
>> workaround, full details to follow shortly ...
> OK. I found I could work around with the following. I wanted to make
> sure I was not screwing it up.
>
> Jeff
>
> // construction/destruction
> // inline void construct(pointer p, const T& t) { new(p) T(t); }
> // Added for Fedora 15/GCC 4.6. Was the previous construct non-compliant?
> inline void construct(pointer p, const T& t = T()) { new(p) T(t);
> inline void destroy(pointer p) { p->~T(); }
>

Your allocator is probably OK now you've made it CopyConstructible but there's 
a problem when using custom allocators with the libstdc++ from GCC 4.6

I'm part way through writing a journal article for the ACCU explaining the 
allocator changes in C++11, as I've not seen anyone try to document them, so 
they must be inferred from the C++ standard.  I'll let you know if/when I 
finish writing that.  Anyway ....

In C++03 the signature for std::allocator<T>::construct is:

void construct(pointer p, const T& t)
{
 ::new ((void*)p) T(t);
}

And custom allocators must have the same signature.

In C++11 std::allocator changes it to a variadic template (and note that the 
type constructed is not necessarily the same as the allocator's value type, 
it's deduced from the pointer type passed in as the first parameter):

template<typename T2, typename... Args>
void construct(T2* p, Args&&... a)
{
 ::new ((void*)p) T2(std::forward<Args>(a)...);
}

Custom allocators are not required to have the same signature, in fact in C++11 
they are not required to provide a 'construct' member at all.

In order to retain backward compatibility with custom allocators using the old 
signature, or with new C++11 allocators with no 'construct' there is a new 
class template allocator_traits, which provides a fallback definition, which 
should be used like so:

zallocator<T> z;
typedef allocator_traits<zallocator<T>> traits;
T* buf = traits::allocate(z, 3);
traits::construct(z, buf+0, t);
traits::construct(z, buf+1);
traits::construct(z, buf+2, 1, 2, 3);

The first construct call would use your zallocator's 'construct' member. The 
second and third would use the default definition provided by allocator_traits, 
because your zallocator doesn't have a suitable 'construct' member.  This makes 
everything work perfectly, whether using C++03-style allocators or C++11-style 
allocators.

The problem is that the libstdc++ in GCC 4.6 doesn't have allocator_traits, so 
the calls above would be done by calling your allocator's construct directly:

zallocator<T> z;
T* buf = z.allocate(3);
z.construct(buf+0, t);
z.construct(buf+1);
z.construct(buf+2, 1, 2, 3);

Obviously this fails if zallocator only provides the C++03 interface, which is 
the error you're getting.

I've added allocator_traits so it will be in GCC 4.7, but until then the 
workaround would be to add this to your allocator:

#if defined(__GXX_EXPERIMENTAL_CXX0X__) \
 && __GNUC__ == 4 && __GNUC_MINOR__ < 7

template<typename U, typename... Args>
void construct(U* p, Args&&... a)
{
 ::new ((void*)p) U(std::forward<Args>(a)...);
}

template<typename U>
void destroy(U* p)
{
 delete p;
}

#endif

That should let your allocator work with any code (such as libsdc++ in gcc 4.6) 
which incorrectly relies on the C++11 allocator interface instead of making use 
of allocator_traits

Original issue reported on code.google.com by noloa...@gmail.com on 18 Aug 2011 at 1:38

GoogleCodeExporter commented 9 years ago

Original comment by noloa...@gmail.com on 18 Aug 2011 at 2:04