[boost.test] Non-conforming operator new, AFAICT

Hello, boost.test currently contains an assortment of new operators which IMO are not conforming to the C++ std. The implementation basically looks like this: p = std::malloc(n); if (!p) throw std::bad_alloc(); This ignores the fact the std::malloc() is allowed to return either 0 or some unique pointer on zero sized requests, whereas a C++ allocation function _must_ return a unique pointer for each zero sized request. If I'm correct, this could be easily fixed by changing all occurences of "p = std::malloc(n)" to "p = std::malloc(n ? n : 1)" or something similar. Regards, Markus

Hello,
boost.test currently contains an assortment of new operators which IMO are not conforming to the C++ std.
The implementation basically looks like this:
p = std::malloc(n); if (!p) throw std::bad_alloc();
This ignores the fact the std::malloc() is allowed to return either 0 or some unique pointer on zero sized requests, whereas a C++ allocation function _must_ return a unique pointer for each zero sized request.
If I'm correct, this could be easily fixed by changing all occurences of "p = std::malloc(n)" to "p = std::malloc(n ? n : 1)" or something similar.
Ok. Applied. Gennadiy

On 12/22/05 10:45 AM, "Gennadiy Rozental" <gennadiy.rozental@thomson.com> wrote: [Markus Schöpflin <markus.schoepflin@comsoft.de> wrote:] [SNIP]
This ignores the fact the std::malloc() is allowed to return either 0 or some unique pointer on zero sized requests, whereas a C++ allocation function _must_ return a unique pointer for each zero sized request.
If I'm correct, this could be easily fixed by changing all occurences of "p = std::malloc(n)" to "p = std::malloc(n ? n : 1)" or something similar.
Ok. Applied.
Shouldn't it be applied only if std::malloc returns NULL on 0-sized allocations? A std::malloc implementation that returns unique pointers for zero sizes is OK. Maybe something like: void * p = std::malloc( n ); if ( !n && !p ) p = std::malloc( 1 ); return p; would be better? -- Daryle Walker Mac, Internet, and Video Game Junkie darylew AT hotmail DOT com

If I'm correct, this could be easily fixed by changing all occurences of "p = std::malloc(n)" to "p = std::malloc(n ? n : 1)" or something similar.
Ok. Applied.
Shouldn't it be applied only if std::malloc returns NULL on 0-sized allocations? A std::malloc implementation that returns unique pointers for zero sizes is OK. Maybe something like:
void * p = std::malloc( n ); if ( !n && !p ) p = std::malloc( 1 ); return p;
would be better?
Does it matter? I do not want to complicate things too much. Gennadiy

Daryle Walker wrote:
Shouldn't it be applied only if std::malloc returns NULL on 0-sized allocations? A std::malloc implementation that returns unique pointers for zero sizes is OK. Maybe something like:
void * p = std::malloc( n ); if ( !n && !p ) p = std::malloc( 1 ); return p;
would be better?
As far as I can tell, memory allocators usually allocate some smallest possible quantity (say 8 or 16 bytes), no matter how small the size is. This happens even on zero sized reuqests, when the allocator returns a non zero pointer. So my proposed fix just does what the allocator does anyway. I don't think we need the extra complication. Besides, zero sized requests are probably rare anyway. Markus

Markus Schöpflin wrote:
boost.test currently contains an assortment of new operators which IMO are not conforming to the C++ std.
The implementation basically looks like this:
p = std::malloc(n); if (!p) throw std::bad_alloc();
This ignores the fact the std::malloc() is allowed to return either 0 or some unique pointer on zero sized requests, whereas a C++ allocation function _must_ return a unique pointer for each zero sized request.
I think it is guaranteed that a C++ allocation request (operator new) is never asked to allocate 0 bytes, thus the problem doesn't exist. Regards, Daniel

Daniel Frey wrote:
Markus Schöpflin wrote:
boost.test currently contains an assortment of new operators which IMO are not conforming to the C++ std.
The implementation basically looks like this:
p = std::malloc(n); if (!p) throw std::bad_alloc();
This ignores the fact the std::malloc() is allowed to return either 0 or some unique pointer on zero sized requests, whereas a C++ allocation function _must_ return a unique pointer for each zero sized request.
I think it is guaranteed that a C++ allocation request (operator new) is never asked to allocate 0 bytes, thus the problem doesn't exist.
I'm sorry to insist, but what makes you think this might be the case? I have never ever heard of such a guarantee, but this of course doesn't mean much. Could you please point me to some reference for this? Markus

Markus Schöpflin wrote:
Daniel Frey wrote:
Markus Schöpflin wrote:
boost.test currently contains an assortment of new operators which IMO are not conforming to the C++ std.
The implementation basically looks like this:
p = std::malloc(n); if (!p) throw std::bad_alloc();
This ignores the fact the std::malloc() is allowed to return either 0 or some unique pointer on zero sized requests, whereas a C++ allocation function _must_ return a unique pointer for each zero sized request.
I think it is guaranteed that a C++ allocation request (operator new) is never asked to allocate 0 bytes, thus the problem doesn't exist.
I'm sorry to insist, but what makes you think this might be the case? I have never ever heard of such a guarantee, but this of course doesn't mean much. Could you please point me to some reference for this?
I think operator new is intended to be called by new T. As zero sized types don't exist, operator new will never be called with n==0. But there's nothing which prevents you from calling operator new directly, so maybe it's even possible for operator new. What do the experts say? Was this intended or is it a defect report? Or am I missing something? (Note: I'm not talking about operator new[], which can be asked to allocate an array of zero objects as per 5.3.4/7) Regards, Daniel

Daniel Frey wrote:
I think operator new is intended to be called by new T. As zero sized types don't exist, operator new will never be called with n==0.
But there's nothing which prevents you from calling operator new directly, so maybe it's even possible for operator new.
What do the experts say? Was this intended or is it a defect report? Or am I missing something?
(Note: I'm not talking about operator new[], which can be asked to allocate an array of zero objects as per 5.3.4/7)
Hmm, what you're saying sounds reasonable, but nevertheless I was observing an exception due to a zero sized request somehow generated by the standard library implemenation on my platform. 18.4.1.1 defines the effects of operator new() as follows: 'The allocation function (3.7.3.1) called by a new-expression (5.3.4) to allocate size bytes of storage suitably aligned to represent any object of that size.' An allocation function must comply to the behaviour required in 3.7.3.1, therefore I would think that operator new() has to comply to this behaviour as well. And nothing forbids others callers (besides the new-expression) of operator new(), AFAICT. Markus
participants (4)
-
Daniel Frey
-
Daryle Walker
-
Gennadiy Rozental
-
Markus Schöpflin