Legality of using operator delete on a pointer obtained from placement new

后端 未结 4 1203
时光说笑
时光说笑 2020-12-01 15:19

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         


        
相关标签:
4条回答
  • 2020-12-01 15:24

    The Standard rules at [basic.stc.dynamic.deallocation]p3

    Otherwise, the value supplied to operator delete(void*) in the standard library shall be one of the values returned by a previous invocation of either operator new(size_t) or operator new(size_t, const std::nothrow_t&) in the standard library, and the value supplied to operator delete[](void*) in the standard library shall be one of the values returned by a previous invocation of either operator new[](size_t) or operator new[](size_t, const std::nothrow_t&) in the standard library.

    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.

    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.

    0 讨论(0)
  • 2020-12-01 15:25

    I found this in the library section of the standard, which is about as counter-intuitive a location (IMO) as possible:

    C++0x FCD (and n3225 draft) section 18.6.1.3, [new.delete.placement]:

    These functions are reserved, a C ++ program may not define functions that displace the versions in the Standard C ++ library (17.6.3). The provisions of (3.7.4) do not apply to these reserved placement forms of operator new and operator delete.

    void*  operator  new(std::size_t  size,  void*  ptr)  throw();
    void*  operator  new[](std::size_t  size,  void*  ptr)  throw();
    void  operator  delete(void*  ptr,  void*)  throw();
    void  operator  delete[](void*  ptr,  void*)  throw();
    

    Still, the section defining legal expressions to pass to delete is 5.3.5, not 3.7.4.

    0 讨论(0)
  • 2020-12-01 15:38

    I suppose you might get away with it (on a particular compiler) if

    1. new/delete are implemented in terms of malloc/free and
    2. the placement new actually uses the same mechanism for keeping track of the destructor associated with allocations as the standard new, so that the call to delete could find the right destructor.

    But there is no way it can be portable or safe.

    0 讨论(0)
  • 2020-12-01 15:47

    The compiler doesn't really care that p comes from a placement new call, so it won't prevent you from issuing delete on the object. In that way, your example can be considered "legal".

    That won't work though, since "placement delete" operators cannot be called explicitly. They're only called implicitly if the constructor throws, so the destructor can run.

    0 讨论(0)
提交回复
热议问题