[Date Prev][Date Next] [Thread Prev][Thread Next] [Date Index] [Thread Index]

Re: [OT] C++ question re. dyn. mem.

On Tue, 05 Aug 2003 22:00:13 +0200, Pigeon wrote:

>> No. You have to delete the original pointer (with the original type).
>> Everything else is undefined behaviour, i.e. it could work, it could
>> leak memory (completely or partly), it could crash, or even print "42".
>> It might even work sometimes, and fail mysteriously at other times.
> Interesting. I figured that the actual allocation/deallocation would end
> up being handled by a call to malloc() / free(), and free() only cares
> about having the correct value for the (void *) pointer.

That's how most implementations of C++ work. However, you can't count on
it. I figure that the stronger requirements which C++ puts on the caller
of "delete" might allow for more efficient implementation of the C++
freestore that C's heap did (as a side effect, the size of the memory
chunk is known without any magic fields). Don't know for sure. And
finally, don't forget that each C++ class can have an associated
destructor. For the destructor call, C++ needs to know what kind of object
we are destroying.

The relevant quote from Our Holy Standard of C++, section 5.3.5(2), reads:

> {...} In the first alternative (delete object), the value of the operand
> of delete shall be a pointer to a non-array object or a pointer to a
> sub-object (1.8) representing a base class of such an object (clause
> 10). If not, the behavior is undefined. In the second alternative
> (delete array), the value of the operand of delete shall be the pointer
> value which resulted from a previous array new-expression.72) If not,
> the behavior is undefined. [Note: this means that the syntax of the
> delete-expression must match the type of the object allocated by new,
> not the syntax of the new-expression. ] [Note: a pointer to a const type
> can be the operand of a delete-expression; it is not necessary to cast
> away the constness (5.2.11) of the pointer expression before it is used
> as the operand of the delete-expression. ]

The two "alternatives" here refer to the single-object delete syntax and
the delete[] syntax for arrays. Please note that the text in square
brackets was not inserted by me; it's straight from the original.

The next paragraph (3) discusses derived objects:

> In the first alternative (delete object), if the static type of the
> operand is different from its dynamic type, the static type shall be a
> base class of the operand's dynamic type and the static type shall have
> a virtual destructor or the behavior is undefined. In the second
> alternative (delete array) if the dynamic type of the object to be
> deleted differs from its static type, the behavior is undefined.73)

The terms "static type" and "dynamic type" don't apply cleanly here (as
structs and ints aren't related in any way). So I think (2) is more
relevant (I'm not a language lawyer).

Footnote 73 is interesting as well:

> 73) This implies that an object cannot be deleted using a pointer of
> type void* because there are no objects of type void.

While footnotes (and the notes above, too) are not part of the normative
text, they clearly state the intention of the authors.

> Would it not be the case, though, in the barebones example given, that
> MJM's '_wrong_ assumption' would be correct, and 'it' would work, even
> if in a more general case it might not?

No, it's not correct from the formal point of view. Plus, it's not clean
code. Nevertheless it _may_ work as expected, depending on the
implementation of your compiler and the nature of your code.

> Or would it have been better for C++ to have been named D to stop people
> wanting to think like this?

The malloc/free subsystem is still there, and it works the same way as it
did in C. (Not surprisingly, freeing new'ed objects and deleting malloc'ed
objects is not formally allowed either.)

Best Regards,   |   Hi! I'm a .signature virus. Copy me into
 Sebastian      |   your ~/.signature to help me spread!

Reply to: