Why is not deleting an object that has a destructo

2019-01-19 14:59发布

问题:

This answer quotes C++11 Standard 3.8:

if there is no explicit call to the destructor or if a delete-expression (5.3.5) is not used to release the storage, the destructor shall not be implicitly called and any program that depends on the side effects produced by the destructor has undefined behavior.

The part about the destructor not being called is clear. Now suppose the skipped destructor had a side effect that should have affected the program behavior.

Why is the program behavior undefined now? Why wouldn't the side effects be skipped (since the destructor is not called) and the program run normally just without side effects applied?

回答1:

The important part is the first part of that paragraph (emphasis mine):

A program may end the lifetime of any object by reusing the storage which the object occupies ...

If you simply reuse the storage for an object whose destructor has not been called, then you get undefined behaviour. For example, the object could have started a thread, or registered a callback, or some other action where an external component might expect the object to still exist.



回答2:

In this case, we do have a precise answer. The specific line was introduced to resolve CWG 1116, "Aliasing of union members".



回答3:

Your question does not make sense.

Why wouldn't the side effects be skipped (since the destructor is not called) and the program run normally just without side effects applied?

They are skipped, because they would have been triggered by the destructor and it has not been called.

My reading of:

and any program that depends on the side effects produced by the destructor has undefined behavior.

is simple, I view it in light of RAII. Example:

#include "Object.hpp"

struct Manager: private boost::noncopyable {
  union Raw {
    char _[sizeof(Object)];
    Object o;
  };
  static Raw raw;

  Manager() { new (raw.o) Object(); }
  ~Manager() { raw.o.~Object(); }
};

Now, if I allocate a Manager, forgets to destroy it, and allocates a new one, I am in a pinch for I am overwriting the storage of the first created Object with a second one even though it is still "alive". This is undefined behavior.



回答4:

I believe this is put into the standard to allow for garbage collection. And to point out that C++ behaves differently that some other languages, by not calling destructors while collecting.

It specifically says that storage can be reused without calling the destructors of the objects in that memory area. If the program depends on the destructors being run, it will not work as expected.

If it doesn't depend on the destructors, all is fine.