Topic: Defect Report: Erroneous semantics for new-expression when an exception is thrown
Author: iltchenko@yahoo.com (Andrei Iltchenko)
Date: 26 Jun 01 14:18:01 GMT Raw View
[Moderator's note: this defect report has been
forwarded to the C++ committee. -moderator(fjh).]
Section: 5.3.4 - New [expr.new]
Submitter: Andrei Iltchenko (iltchenko@yahoo.com)
According to the C++ Standard section 5.3.4 [expr.new] paragraph 21
"it is unspecified whether the allocation function is called before
evaluating the constructor arguments or after evaluating the
constructor arguments but before entering the constructor."
On top of that paragraph 17 of the same section insists that "If any
part of the object initialization described above [Footnote: This may
include evaluating a new-initializer and/or calling a constructor.]
terminates by throwing an exception and a suitable deallocation
function is found, the deallocation function is called to free the
memory in which the object was being constructed... If no unambiguous
matching deallocation function can be found, propagating the exception
does not cause the object's memory to be freed..."
Now suppose we have:
1. An implementation that always evaluates the constructor arguments
first (for a new-expression that creates an object of a class type and
has a new-initializer) and calls the allocation function afterwards.
2. A class like this:
struct copy_throw {
copy_throw(const copy_throw&)
{ throw std::logic_error("Cannot copy!"); }
copy_throw(long, copy_throw)
{ }
copy_throw()
{ }
};
3. And a piece of code that looks like the one below:
int main()
try {
copy_throw an_object, /* undefined behaviour */
* a_pointer = ::new copy_throw(0, an_object);
return 0;
}
catch(const std::logic_error&)
{ }
Here the new-expression '::new copy_throw(0, an_object)' throws an
exception when evaluating the constructor's arguments and before the
allocation function is called. However, 5.3.4 [expr.new] paragraph 17
prescribes that in such a case the implementation shall call the
deallocation function to free the memory in which the object was being
constructed, given that a matching deallocation function can be found.
So a call to the Standard library deallocation function '::operator
delete(void*)' shall be issued, but what argument is an implementation
supposed to supply to the deallocation function? As per 5.3.4
[expr.new] paragraph 17 - the argument is the address of the memory in
which the object was being constructed. Given that no memory has yet
been allocated for the object, this will qualify as using an invalid
pointer value, which is undefined behaviour by virtue of 3.7.3.2
[basic.stc.dynamic.deallocation] paragraph 4.
Suggested resolution:
Change the first sentence of 5.3.4 [expr.new] paragraph 17 to read:
If the memory for the object being created has already been
successfully allocated and any part of the object initialization
described above...
Regards,
Andrei Iltchenko.
---
[ comp.std.c++ is moderated. To submit articles, try just posting with ]
[ your news-reader. If that fails, use mailto:std-c++@ncar.ucar.edu ]
[ --- Please see the FAQ before posting. --- ]
[ FAQ: http://www.research.att.com/~austern/csc/faq.html ]