usa qué que poo para how ejemplos define crear constructores como c++ exception signals destructor exit

qué - que es un constructor y un destructor en c++



¿En qué circunstancias no se llamarán los destructores de C++? (8)

Sé que mis destructores son llamados en el desenrollado normal de la pila y cuando se lanzan excepciones, pero no cuando se llama a exit ().

¿Hay algún otro caso en el que mis destructores no sean llamados? ¿Qué pasa con señales como SIGINT o SIGSEGV? Supongo que para SIGSEGV no se llaman, pero para SIGNINT lo son, ¿cómo sé qué señales desenrollarán la pila?

¿Hay alguna otra circunstancia donde no serán llamados?


¿Hay alguna otra circunstancia donde no se llamarán [destructores]?

  1. Saltos largos: estos interfieren con el proceso natural de desenrollado de la pila y a menudo conducen a un comportamiento indefinido en C ++.
  2. Salidas prematuras (ya las señaló, aunque vale la pena señalar que arrojar mientras la pila ya se desenrolla como resultado de una excepción arrojada conduce a un comportamiento indefinido y esta es la razón por la que nunca deberíamos arrojar los dtors)
  3. Lanzar desde un constructor no invoca al dtor para una clase. Por esta razón, si asigna varios bloques de memoria administrados por varios punteros diferentes (y no punteros inteligentes) en un ctor, debe usar bloques de prueba de nivel de función o evitar el uso de la lista de inicializadores y tener un bloque try / catch en el ctor cuerpo (o mejor aún, simplemente use un puntero inteligente como scoped_ptr ya que cualquier miembro inicializado con éxito hasta el momento en una lista de inicializadores será destruido aunque no se invoque el controlador de clase).
  4. Como se señaló, si no se hace virtual un dtor cuando se borra una clase a través de un puntero base, podría no invocarse a los dtors de la subclase (comportamiento indefinido).
  5. Si no se puede llamar al operador coincidente, eliminar / eliminar [] para un operador nuevo / nuevo [] llamada (comportamiento indefinido - puede no invocar dtor).
  6. No se puede invocar manualmente al dtor cuando se usa la ubicación nueva con un asignador de memoria personalizado en la sección de desasignación.
  7. Usando funciones como memcpy que solo copia un bloque de memoria a otro sin invocar copiadores. Las funciones de mem * son mortales en C ++ ya que arrasan con los datos privados de una clase, sobrescriben los vtables, etc. El resultado suele ser un comportamiento indefinido.
  8. Creación de algunos de los punteros inteligentes (auto_ptr) en un tipo incompleto, vea esta discussion


Básicamente hay dos situaciones en las que se llaman destructores: Desenrollar la pila al final de la función (o en excepciones), si alguien (o un contador de referencia) llama a eliminar.

Una situación especial se encuentra en los objetos estáticos: se destruyen al final del programa en at_exit, pero esta sigue siendo la segunda situación.

La señal que deja en el punto de salida de at_exit puede depender, kill -9 matará el proceso inmediatamente, otras señales le indicarán que salga, pero cómo exactamente depende de la devolución de la señal.


El estándar de C ++ no dice nada sobre cómo deben manejarse las señales específicas: muchas implementaciones pueden no ser compatibles con SIGINT , etc. No se SIGINT destructores si se exit() o abort() o terminate() .

Edición: acabo de realizar una búsqueda rápida a través del estándar C ++ y no encuentro nada que especifique cómo las señales interactúan con la vida útil de los objetos, tal vez alguien con mejores estándares que yo podría encontrar algo.

Edición adicional: Al responder a otra pregunta, encontré esto en el Estándar:

Al salir de un ámbito (independientemente de cómo se realice), se invocan destructores (12.4) para todos los objetos construidos con duración de almacenamiento automática (3.7.2) (objetos nombrados o temporales) que se declaran en ese ámbito, en el orden inverso al de su declaración.

Entonces parece que los destructores deben ser llamados al recibir una señal.


Otro caso en el que no se llamarán es si está usando un polimorfismo y no ha hecho virtuales sus destructores base.


Si una función o método tiene una especificación throws y arroja algo que NO está cubierto por la especificación, el comportamiento predeterminado es salir inmediatamente. La pila no se desenrolla y los destructores no son llamados.

Las señales POSIX son una construcción específica del sistema operativo y no tienen noción del alcance del objeto C ++. En general, no se puede hacer nada con una señal excepto, quizás, atraparla, establecer una variable de indicador global y luego manejarla más tarde en su código C ++ después de que el controlador de señal se cierre.

Las versiones recientes de GCC le permiten lanzar una excepción desde controladores de señal síncronos, lo que da como resultado el proceso esperado de desenrollado y destrucción. Sin embargo, este es un sistema muy operativo y un compilador específico.


Una señal por sí sola no afectará la ejecución del hilo actual y, por lo tanto, la invocación de destructores, porque es un contexto de ejecución diferente con su propia pila, donde sus objetos no existen. Es como una interrupción: se maneja en algún lugar fuera del contexto de ejecución y, si se maneja, el control se devuelve a su programa.

Al igual que con multihilo, C ++ el lenguaje no conoce una noción de señales. Estos dos son completamente ortogonales entre sí y están especificados por dos estándares no relacionados. Cómo interactúan depende de la implementación, siempre y cuando no rompa ninguno de los estándares.

Como nota al margen, otro caso es cuando el destructor del objeto no se llamará cuando su constructor arroje una excepción. Sin embargo, se seguirán llamando a los destructores de los miembros.


abort termina el programa sin ejecutar destructores para objetos de duración de almacenamiento automática o estática como dice Standard. Para otras situaciones, debe leer los documentos específicos de la implementación.