In what circumstances will C ++ destructors not be called?

I know that my destructors are called during normal stack unwinding and when exceptions are thrown, but not when exit () is called.

Are there any other cases where my destructors will not be called? What about signals like SIGINT or SIGSEGV? I suppose that for SIGSEGV they are not called, but for SIGNINT they are, how do I know which signals are stacked?

Are there any other circumstances in which they will not be caused?

+40
c ++ exception destructor signals exit
Jul 05 2018-10-12T00:
source share
8 answers

Are there other circumstances in which they [destructors] will not be called?

  • Long transitions: they interfere with the process of expanding the natural stack and often lead to undefined behavior in C ++.
  • Premature exits (you have already pointed to them, although it is worth noting that throwing while the stack is being reset as a result of throwing an exception leads to undefined behavior, and therefore we should never throw from dtors)
  • A throw from the constructor does not call a dtor for the class. That's why if you allocate several memory blocks controlled by several different pointers (rather than smart pointers) in ctor, you need to use try blocks at the function level or avoid using a list of initializers and have a try / catch block in ctor (or, even better, just use a smart pointer like scoped_ptr, since any member successfully initialized so far in the initializer list will be destroyed even if the dtor class is not called).
  • As indicated, the inability to make dtor virtual when the class is deleted using the base pointer may not cause the behavior of the dtors (undefined) subclass.
  • Inability to call the matching operator delete / delete [] for the new / new [] call operator (undefined behavior - may not call dtor).
  • It is not possible to manually call dtor when using a new placement using a dedicated memory allocator in the deallocate section.
  • Using functions like memcpy, which copies only one block of memory to another without causing ctors to copy. mem * functions in C ++ are deadly because they accumulate class personal data, overwrite vtables, etc. The result is usually undefined behavior.
  • Activating some smart pointers (auto_ptr) on an incomplete type, see this discussion
+45
Jul 05 '10 at 13:23
source share

The C ++ standard does not say anything about how to process specific signals - many implementations may not support SIGINT , etc. Destructors will not be called if exit() or abort() or terminate() called.

Edit: I just had a quick search on the C ++ standard, and I can't find anything that would indicate how signals interact with objects of life - maybe someone with better standards-fu than I could find something- then?

Further editing:. Answering another question, I found this in the standard:

When leaving the scope (however), destructors (12.4) for all constructed objects with automatic storage duration (3.7.2) (named objects or temporary) that are declared in this area, in the reverse order of their declaration.

So, it seems that destructors should be called when a signal is received.

+7
Jul 05 2018-10-05T00:
source share

The signal itself will not affect the execution of the current thread and, therefore, the call of destructors, because it is a different execution context with its own stack, where your objects do not exist. It's like an interrupt: it is processed somewhere outside the execution context, and, if processed, the control returns to your program.

As with multithreading, C ++ does not know the concept of signals. The two are completely orthogonal to each other and are defined by two unrelated standards. How they interact depends on the implementation if it does not violate any of the standards.

As a side note, another case is that the destructor object will not be called when its constructor throws an exception. However, the destructors of the participants will be called.

+3
Jul 05 2018-10-05T00:
source share

Otherwise, they will not be called if you use polymorphism and have not made your base destructors virtual.

+3
Jul 05 '10 at 13:14
source share

abort terminates the program without executing destructors for objects of automatic or static storage duration, as Standard says. For other situations, you should read specific documents related to the implementation.

+2
Jul 05 2018-10-12T00:
source share

If a function or method has a throw specification and throws something that is not covered by the specification, the default behavior is to exit the system immediately. The stack does not unwind, and destructors are not called.

POSIX signals are an operating system-specific design and do not have a notion of the scope of C ++ objects. As a rule, you cannot do anything with the signal, with the possible exception of a trap, setting a global flag variable, and then processing it later in C ++ code after the signal handler exits.

Recent versions of GCC allow you to exclude synchronous signal handlers, which leads to the expected process of unwinding and destroying. This is a very specific operating system and compiler, although

+2
Jul 05 '10 at 13:59 on
source share

Lots of answers here, but still incomplete!

I found another case where destructors fail. This always happens when an exception hits the library boundary.

See here for more details:

Destructors fail (without stack expansion) when an exception is thrown

+2
Jan 25 '14 at 4:02
source share

Basically, there are two situations where destructors are called: On the stack, they are unwound at the end of the function (or on exceptions) if someone (or the reference counter) calls delete.

One special situation is detected in static objects - they are destroyed at the end of the program via at_exit, but this is still the second situation.

Which signal leaves at_exit may depend on, kill -9 will immediately kill this process, other signals will tell it about the exit, but how exactly it depends on the callback of the signal.

+1
Jul 05 '10 at 12:53 on
source share



All Articles