在从展示位置新获得的指针上使用操作符删除的合法性 [英] Legality of using operator delete on a pointer obtained from placement new
问题描述
我确定这段代码应该是非法的,因为它显然不会工作,但它似乎被C + + 0x FCD允许。
I'm dang certain that this code ought to be illegal, as it clearly won't work, but it seems to be allowed by the C++0x FCD.
class X { /* ... */};
void* raw = malloc(sizeof (X));
X* p = new (raw) X(); // according to the standard, the RHS is a placement-new expression
::operator delete(p); // definitely wrong, per litb's answer
delete p; // legal? I hope not
也许你们中的一个是律师可以解释一下标准是如何禁止的。
Maybe one of you language lawyers can explain how the standard forbids this.
还有一个数组形式:
class X { /* ... */};
void* raw = malloc(sizeof (X));
X* p = new (raw) X[1]; // according to the standard, the RHS is a placement-new expression
::operator delete[](p); // definitely wrong, per litb's answer
delete [] p; // legal? I hope not
This is the closest question I was able to find.
我只是不买参数的标准的语言限制参数的函数 void :: operator delete(void *)
以任何有意义的方式适用于<$ c的操作数$ c> delete 在 delete-expression 中。最好的是,两者之间的连接是非常微小的,并且许多表达式被允许作为操作数 delete
它们不能传递给 void :: operator delete(void *)
。例如:
I'm just not buying the argument that the standard's language restricting arguments to function void ::operator delete(void*)
apply in any meaningful way to the operand of delete
in a delete-expression. At best, the connection between the two is extremely tenuous, and a number of expressions are allowed as operands to delete
which are not valid to pass to void ::operator delete(void*)
. For example:
struct A
{
virtual ~A() {}
};
struct B1 : virtual A {};
struct B2 : virtual A {};
struct B3 : virtual A {};
struct D : virtual B1, virtual B2, virtual B3 {};
struct E : virtual B3, virtual D {};
int main( void )
{
B3* p = new E();
void* raw = malloc(sizeof (D));
B3* p2 = new (raw) D();
::operator delete(p); // definitely UB
delete p; // definitely legal
::operator delete(p2); // definitely UB
delete p2; // ???
return 0;
}
我希望这表明一个指针是否可以传递给 void operator delete(void *)
与是否可以使用相同的指针作为 delete
的操作数无关。
I hope this shows that whether a pointer may be passed to void operator delete(void*)
has no bearing on whether that same pointer may be used as the operand of delete
.
推荐答案
[basic.stc.dynamic.deallocation]的标准规则p3
The Standard rules at [basic.stc.dynamic.deallocation]p3
否则,标准库中提供给
operator delete(void *)
的值应为上一次调用<在标准库中的code>运算符new(size_t)或运算符new(size_t,const std :: nothrow_t&)
在标准库中提供给operator delete [](void *)
的值应为之前调用operator new [ ](size_t)
或运算符new [](size_t,const std :: nothrow_t&)
$ b
Otherwise, the value supplied to
operator delete(void*)
in the standard library shall be one of the values returned by a previous invocation of eitheroperator new(size_t)
oroperator new(size_t, const std::nothrow_t&)
in the standard library, and the value supplied tooperator delete[](void*)
in the standard library shall be one of the values returned by a previous invocation of eitheroperator new[](size_t)
oroperator new[](size_t, const std::nothrow_t&)
in the standard library.
您的 delete
调用将调用库的 operator delete(void *)
,除非你已经覆盖它。因为你没有说什么,我会假设你没有。
Your delete
call will call the libraries' operator delete(void*)
, unless you have overwritten it. Since you haven't said anything about that, I will assume you haven't.
上面的shall真的应该是行为未定义,如果没有,所以它不会被误认为是一个可诊断的规则,它不是[lib .res.on.arguments] p1。这是由n3225纠正,所以它不能再错过。
The "shall" above really should be something like "behavior is undefined if not" so it's not mistaken as being a diagnosable rule, which it isn't by [lib.res.on.arguments]p1. This was corrected by n3225 so it can't be mistaken anymore.
这篇关于在从展示位置新获得的指针上使用操作符删除的合法性的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!