delete[] with different type undefined behaviour?

c++ delete
delete called on that is abstract but has non-virtual destructor
virtual destructor c++
c++ destructor
delete called on non-final that has virtual functions but non-virtual destructor
placement delete
c++ delete base class pointer
cannot delete expression of type

I am wondering if this is undefined behavior:

#include <stdint.h>

int main() {
  auto* p = new uint8_t[32];
  float* c = reinterpret_cast<float*>(p);
  delete[] c;
}

In the standard there is

If not, the behavior is undefined. In the second alternative (delete array), the value of the operand of delete may be a null pointer value or a pointer value that resulted from a previous array new-expression.79 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. — end note ]

So interpreting the somewhat unclear phrase

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

I can say the above is Undefined Behavior, correct?


Yes, the behaviour is undefined.

The pointer passed to delete[] must be the same type as the one you get back from new[].

Note that for delete and new, the pointer submitted to delete is allowed to be related by polymorphism.

OOP52-CPP. Do not delete a polymorphic object , Deleting an object through a pointer to a type without a virtual destructor results When b is deleted, it results in undefined behavior because Base does not have a Search for other vulnerabilities resulting from the violation of this rule on the  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.


Yes, the code in indeed Undefined Behavior. The phrasing means that it would still be UB when you would rewrite it as

int main() {
  void* p;
  {
     using T = uint8_t;
     p = new T [32];
  }
  {
    using T = float;
    T* c = reinterpret_cast<float*>(p);
    delete[] c; // The behaviour is still undefined.
  }
}

IOW, the types really have to match exactly, not just in name.

V772. Calling the 'delete' operator for a void pointer will cause , section 5.3.53 such use of delete results in undefined behavior. code is that the compiler does not actually know the type of the 'ptr' pointer. I found the following snippet in the C++03 Standard under 5.3.5 [expr.delete] p3:. 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 operand’s dynamic type and the static type shall have a virtual destructor or the behavior is undefined.


It is undefined behavior to call delete[] p; if p has a different type that what new[] returned.

Notably:

struct Base { virtual ~Base() = default; };
struct Derived: Base { int a; };

int main() {
    Base* p = new Derived[5];
    delete[] p;
}

Is also undefined behavior.


@Justin provided the relevant standard quote in a comment see it here:

5.3.5 [expr.delete]

(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. 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.

Note how there is no provision for polymorphic relationship in the delete array case I emphasized; contrary to the delete object case.

delete expression, For other types, the alignment-unaware deallocation functions (without a If the type is complete and if, for the delete[] only, the operand is a pointer to a of the base class must be virtual, otherwise the behavior is undefined. Does the above code invoke Undefined Behavior? It depends. From C11 draft 6.3.2.3/7: A pointer to an object type may be converted to a pointer to a different object type. If the resulting pointer is not correctly aligned) for the referenced type, the behavior is undefined. As the alignment


operator delete, operator delete[], Type support (basic types, RTTI, type traits) Common vocabulary types the pointer value into another variable, is undefined behavior. Examples of undefined behavior are memory accesses outside of array bounds, signed integer overflow, null pointer dereference, more than one modifications of the same scalar in an expression without any intermediate sequence point (until C++11) that are unsequenced (since C++11), access to an object through a pointer of a different type, etc


Undefined Behavior, int array[] = {1, 2, 3, 4, 5}; array[5] = 0; // Undefined behavior if the static type of the object to be deleted is different from its dynamic type, the static type shall be  Undefined behaviors may also cause security vulnerabilities, especially due the cases when array out of bound is not checked (causes buffer overflow attack). Advantages of Undefined Behavior C and C++ have undefined behaviors because it allows compilers to avoid lots of checks.


operator delete[] - C++ Reference, void operator delete[] (void* ptr, const std::nothrow_t& nothrow_constant) throw(); operator delete[] is a regular function that can be called explicitly just as any other function. array (if these are of a class type), and then calls an array deallocation function. Notice that an invalid value of ptr causes undefined behavior. The C++ Standard, [expr.delete], paragraph 3 [ISO/IEC 14882-2014], states the following:. 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.