5

Can i use smth like the following code:

int main()
{
    int* foo = new int;
    double* bar = reinterpret_cast<double*>(foo);
    delete bar;
}

Is it UB?

I think that we need to call operator delete only for pointers returned by operator new, but what about casting in this case?

I think that it's UB since the reinterpret_cast don't give any guarantees about the resulting pointer. Am i right?

Can somebody post the right quote from the standard, please?

FrozenHeart
  • 19,844
  • 33
  • 126
  • 242

3 Answers3

6

§5.3.5/2 "In the first alternative (delete object), the value of the operand of delete may be a null pointer value, a pointer to a non-array object created by a previous new-expression, or a pointer to a subobject (1.8) representing a base class of such an object (Clause 10). If not, the behavior is undefined." Since bar points to a double, it does not point to an object created by a previous new-expression (which created an int).

James Kanze
  • 150,581
  • 18
  • 184
  • 329
  • What is the static and dynamic type in this case? – FrozenHeart Jun 24 '13 at 11:30
  • `int` and `double`, respectively. But even if the wording of the standard is too convoluted to understand, just consider that you're invoking the wrong constructor with what you do. This should be obvious even without having the above quote. Both destructors are trivial as it happens, so it "will work", but it's still very obviously UB. – Damon Jun 24 '13 at 11:32
  • @NikitaTrophimov, More here: http://stackoverflow.com/questions/1347691/static-vs-dynamic-type-checking-in-c – chris Jun 24 '13 at 11:33
  • @Damon You have different opinion than Tadeusz Kopec in other answer. Who's right? :) – FrozenHeart Jun 24 '13 at 11:34
  • @NikitaTrophimov: `operator delete` calls the destructor. If you invoke `B::~B` on an object of unrelated type `A`, please tell me what _meaningful_ actions this destructor could perform to destroy the object, in your opinion. Incidentially, the destructors of `int` and `double` both do nothing at all, and "nothing" is the same as "nothing" but that's just a lucky coincidence. And then consider that `delete` does need to actually free a block of memory _of some size_ which might or might not belong to _some pool_, too. It _might_ know from metadata stored in the allocated block, but that's UB. – Damon Jun 24 '13 at 11:38
  • @NikitaTrophimov: You are of course allowed to invoke `operator delete` on a derived instance via a base pointer, if the destructor is virtual. But only in this case, never otherwise. That's not the case in your example. – Damon Jun 24 '13 at 11:44
  • 1
    @NikitaTrophimov The standard only makes the distinction between static and dynamic type in the case of polymorphic objects. In the text I quote, there is no mention of it: it simply lists the three legal cases: a null pointer, a pointer to an object created by a previous new-expression, and a pointer to Base when the object created by the new-expression was a Derived. There are additional constraints, specified later, but in this case, we've already failed here. – James Kanze Jun 24 '13 at 11:56
2

From 5.3.5-3:

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

Leaving aside possible problems in using reinterpret_cast here, this is UB because the types do not match. Imagine some nontrivial type, then you can easily see this as the "wrong" dtor would be called.

Additionally using the result of reinterpret_cast for anything else than casting it back is mostly unspecified by the standard.

PlasmaHH
  • 15,673
  • 5
  • 44
  • 57
0

Here you are:

5.3.5 point 3: In the first alternative (delete object), if the static type of the object to be deleted is different from its dynamic type, the static type shall be a base class of the dynamic type of the object to be deleted and the static type shall have a virtual destructor or the behavior is undefined.

As for questions of what is static and dynamic type:

1.3.7 dynamic type (glvalue)
type of the most derived object (1.8) to which the glvalue denoted by a glvalue expression refers [ Example: if a pointer (8.3.1) p whose static type is “pointer to class B” is pointing to an object of class D, derived from B (Clause 10), the dynamic type of the expression *p is “D.” References (8.3.2) are treated similarly. —end example ]

1.3.23 static type
type of an expression (3.9) resulting from analysis of the program without considering execution semantics [Note: The static type of an expression depends only on the form of the program in which the expression appears, and does not change while the program is executing. —end note]

Tadeusz Kopec for Ukraine
  • 12,283
  • 6
  • 56
  • 83