7

Is OK to throw an exception when 0 is passed to allocate method?

Thank you.

P.S.

If n == 0, the return value is unspecified.

Does it mean that allocate shouldn't throw an exception? I am inclined to think that if throwing wasn't allowed for n==0, then the standard would clearly spell it out.

1
  • It is not standard compliant for the allocator to throw an exception on a zero length allocation. Commented May 19, 2011 at 23:09

2 Answers 2

7

All the standard has to say (§20.1.5/2) is that given

  • T – any type
  • X – an Allocator class for type T
  • a – a value of type X&
  • n – a value of type X::size_type,

the return value of the expression a.allocate(n) is unspecified if n equals 0.

One one hand, given that X::allocate doesn't have any mandated exception specification and explicitly may throw std::bad_alloc, I don't see why it couldn't throw some other type of exception as well. On the other hand, the wording specifically calls out the condition wherein n equals zero and directly implies that there is a return value, meaning you shouldn't throw. I think it may be open to some interpretation, but personally I'd side with the latter and consider it an unexceptional code-path.

Sign up to request clarification or add additional context in comments.

1 Comment

Thanks. I knew that that the return value is unspecified for n == 0, but wasn't sure about throwing an exception.
5

The standard demands that an allocation of size 0 shall return a pointer to a memory block of 1 byte size, Brb, looking for relevant standards paragraph.


Edit:
First, I only got the FDIS of C++0x/11 handy (not at home...), but I believe the wording was similar in C++98/03.

Next, it seems I was wrong. It is nowhere stated that the allocator shall return a memory block of size 1. My memory served me wrong. :( Though, I found this little paragraph under 3.7.4.2 [basic.stc.dynamic.allocation] p2:

Even if the size of the space requested is zero, the request can fail. If the request succeeds, the value returned shall be a non-null pointer value (4.10) p0 different from any previously returned value p1, unless that value p1 was subsequently passed to an operator delete. The effect of dereferencing a pointer returned as a request for zero size is undefined.35)

At the end of the same site:

35) The intent is to have operator new() implementable by calling std::malloc() or std::calloc(), so the rules are substantially the same. C++ differs from C in requiring a zero request to return a non-null pointer.

(Emphasis mine.)

Now, the FDIS says under 17.6.3.5 [allocator.requirements], in a note on allocate:

a.allocate(n) X::pointer 

Memory is allocated for n objects of type T but objects are not constructed. allocate may raise an appropriate exception. [ Note: If n == 0, the return value is unspecified. —end note ]

(Emphasis mine.)
So, you shall not throw, as a return of something is implied by that note. It is, however, not required to return a 1 byte sized memory block. So, to answer your question: No, you are not allowed to throw in allocate when the size request is 0 when implementing a standard compliant allocator.

10 Comments

Kind of right... the standard does not sanction throwing an exception, but it does not require returning a block of memory either. In particular in Table 32 - Allocator requirements in section 20.1.5 - Allocator requirements, the description of `allocate(n) / allocate(n,u) has a note: [Note: if n==0, the return value is unspecified], so a conforming implementation can return a block of 1 byte, or a null pointer or basically any other thing as long as it is documented by the compiler vendor.
@DavidRodríguez: Does it need to be sanctioned? The standard doesn't mention it either way but Allocator::allocate can already throw and Allocator::allocate doesn't have an exception specification.
@Xeo : I did read it; it says "A C++ implementation provides access to, and management of, dynamic storage via the global allocation functions operator new and operator new[] and the global deallocation functions operator delete and operator delete[]." and the reference section name is "[basic.stc. dynamic.allocation ]", so I think it only applies to new and new[].
@ildjarn: On whether it can / should throw, I am no expert when it comes to that part of the standard, and I understood the return value is unspecified as there has to be a return value, which in the case of an exception would not be the case. Rereading the same block (this time less tired, and not coming from a bar) it does allow for exceptions to be thrown in allocate: Memory is allocated for n objects of type T but objects are not constructed. allocate may raise an appropriate exception. The result is a random access iterator [Note: if n==0, the return value is unspecified]
Now, going around other parts of the standard, I have just found out that you are right. In 3.7.3.1/2, dealing with allocation functions (not exactly allocators, but I guess that both model the same problem) the standard is explicit in that a request for 0 size memory can fail (i.e. throw exception if the exception specification is not empty): Even if the size of the space requested is zero, the request can fail. The whole paragraph is too long to copy here.
|

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.