使用与 new 中使用的指针类型不同的指针删除内存是否安全?
Is it safe to delete memory with a pointer of different type than the used in new?
下面的代码安全吗?是否有解决此问题的 C++ 标准参考?
// SomeStruct is POD: no constructors or destructor
SomeStruct *pSS = new SomeStruct();
void *pV = reinterpret_cast<void*>(pSS);
delete pV;
只有在以下情况下才可以:
你删除了一个指向基的指针,
and 基础 class 有一个虚拟析构函数。
否则,您将陷入非法代码和未定义行为的境地。
C++14 5.3.5/2
If the operand has a class type, the operand is converted to a pointer type by calling the above-mentioned conversion function, and the converted operand is used in place of the original operand for the remainder of this section. 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. 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. 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 ] [ 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. — end note ]
C++14 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. 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.
此外,void
是一个不完整的类型 (C++14 3.9.1/9):
The void
type has an empty set of values. The void
type is an incomplete type that cannot be completed. It is used as the return type for functions that do not return a value. Any expression can be explicitly converted to type cv void
(5.4). An expression of type void
shall be used only as an expression statement (6.2), as an operand of a comma expression (5.19), as a second or third operand of ?:
(5.16), as the operand of typeid
, noexcept
, or decltype
, as the expression in a return statement (6.6.3) for a function with the return type void
, or as the operand of an explicit conversion to type cv void
.
此外,除非您与 C API 交互,否则您应该努力完全避免 void*
。
这不仅是非法的,而且在现代编译器上简直就是一个编译错误。无法删除 void*.
下面的代码安全吗?是否有解决此问题的 C++ 标准参考?
// SomeStruct is POD: no constructors or destructor
SomeStruct *pSS = new SomeStruct();
void *pV = reinterpret_cast<void*>(pSS);
delete pV;
只有在以下情况下才可以:
你删除了一个指向基的指针,
and 基础 class 有一个虚拟析构函数。
否则,您将陷入非法代码和未定义行为的境地。
C++14 5.3.5/2
If the operand has a class type, the operand is converted to a pointer type by calling the above-mentioned conversion function, and the converted operand is used in place of the original operand for the remainder of this section. 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. In the second alternative (delete array), the value of the operand ofdelete
may be a null pointer value or a pointer value that resulted from a previous array new-expression. If not, the behavior is undefined. [ Note: this means that the syntax of the delete-expression must match the type of the object allocated bynew
, not the syntax of the new-expression. — end note ] [ 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. — end note ]
C++14 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. 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.
此外,void
是一个不完整的类型 (C++14 3.9.1/9):
The
void
type has an empty set of values. Thevoid
type is an incomplete type that cannot be completed. It is used as the return type for functions that do not return a value. Any expression can be explicitly converted to type cvvoid
(5.4). An expression of typevoid
shall be used only as an expression statement (6.2), as an operand of a comma expression (5.19), as a second or third operand of?:
(5.16), as the operand oftypeid
,noexcept
, ordecltype
, as the expression in a return statement (6.6.3) for a function with the return typevoid
, or as the operand of an explicit conversion to type cvvoid
.
此外,除非您与 C API 交互,否则您应该努力完全避免 void*
。
这不仅是非法的,而且在现代编译器上简直就是一个编译错误。无法删除 void*.