delete[] with different type undefined behaviour?
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.
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.
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.
#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.
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.
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.
Comments
Post a Comment