std::exit
| Definido en el encabezado <cstdlib>
|
||
void exit( int exit_code );
|
(hasta C++11) | |
[[noreturn]] void exit( int exit_code );
|
(desde C++11) | |
Provoca la terminación normal del programa.
Se realizan varios pasos de limpieza:
|
1) Los objetos con duración de almacenamiento estático se destruyen y se llaman las funciones registradas mediante std::atexit:
a) Los objetos no locales con duración de almacenamiento estático se destruyen en el orden inverso a la finalización de su constructor.
b) Las funciones registradas con std::atexit se llaman en el orden inverso a su registro, excepto que una función se llama después de cualquier función previamente registrada que ya hubiera sido llamada en el momento de su registro.
c) Para cada función
f registrada con std::atexit y cada objeto no local obj de duración de almacenamiento estático,
d) Para cada objeto local obj con duración de almacenamiento estático, obj se destruye como si se hubiera registrado una función que llama al destructor de obj con std::atexit al finalizar el constructor de obj.
|
(hasta C++11) |
|
1) Los destructores de objetos con duración de almacenamiento de hilo local asociados con el hilo actual, los destructores de objetos con duración de almacenamiento estático y las funciones registradas con std::atexit se ejecutan concurrentemente, manteniendo las siguientes garantías:
a) El último destructor para objetos de hilo local está secuenciado-antes del primer destructor para un objeto estático.
b) Si la finalización del constructor o la inicialización dinámica para un objeto de hilo local o estático A estaba secuenciada-antes que el objeto de hilo local o estático B, la finalización de la destrucción de B está secuenciada-antes del inicio de la destrucción de A.
c) Si la finalización de la inicialización de un objeto estático A estaba secuenciada-antes de la llamada a std::atexit para alguna función F, la llamada a F durante la terminación está secuenciada-antes del inicio de la destrucción de A.
d) Si la llamada a std::atexit para alguna función F estaba secuenciada-antes de la finalización de la inicialización de un objeto estático A, el inicio de la destrucción de A está secuenciado-antes de la llamada a F durante la terminación.
e) Si una llamada a std::atexit para alguna función F1 estaba secuenciada-antes de la llamada a std::atexit para alguna función F2, entonces la llamada a F2 durante la terminación está secuenciada-antes de la llamada a F1.
|
(desde C++11) |
- En lo anterior,
- Si alguna función registrada con
atexito cualquier destructor de un objeto estático/de hilo local lanza una excepción, se llama a std::terminate. - Si el compilador optó por elevar la inicialización dinámica de un objeto a la fase de inicialización estática de la inicialización no local, la secuenciación de la destrucción respeta su supuesta inicialización dinámica.
- Si un objeto estático local a una función (de ámbito de bloque) fue destruido y luego esa función es llamada desde el destructor de otro objeto estático y el flujo de control pasa a través de la definición de ese objeto (o si se usa indirectamente, a través de un puntero o referencia), el comportamiento no está definido.
- Si un objeto estático local a una función (de ámbito de bloque) fue inicializado durante la construcción de un subobjeto de una clase o arreglo, solo se destruye después de que todos los subobjetos de esa clase o todos los elementos de ese arreglo hayan sido destruidos.
- Si alguna función registrada con
exit_code es 0 o EXIT_SUCCESS, se devuelve un estado definido por la implementación que indica terminación exitosa. Si exit_code es EXIT_FAILURE, se devuelve un estado definido por la implementación que indica terminación fallida. En otros casos, se devuelve un valor de estado definido por la implementación.La pila no se desenrolla: los destructores de variables con duración de almacenamiento automática no son llamados.
Relación con la función main
Regresar desde la
función main
, ya sea mediante una sentencia
return
o al alcanzar el final de la función, realiza la terminación normal de la función (llama a los destructores de las variables con
duraciones de almacenamiento
automáticas) y luego ejecuta
std::exit
, pasando el argumento de la sentencia return (o
0
si se utilizó el retorno implícito) como
exit_code
.
Parámetros
| exit_code | - | estado de salida del programa |
Ejemplo
#include <cstdlib> #include <iostream> struct Static { ~Static() { std::cout << "Static destructor\n"; } }; struct Local { ~Local() { std::cout << "Local destructor\n"; } }; Static static_variable; // El destructor de este objeto *será* llamado void atexit_handler() { std::cout << "atexit handler\n"; } int main() { Local local_variable; // El destructor de este objeto *no* será llamado const int result = std::atexit(atexit_handler); // El manejador será llamado if (result != 0) { std::cerr << "atexit registration failed\n"; return EXIT_FAILURE; } std::cout << "test\n"; std::exit(EXIT_FAILURE); std::cout << "this line will *not* be executed\n"; }
Salida:
test atexit handler Static destructor
Informes de defectos
Los siguientes informes de defectos que modifican el comportamiento se aplicaron retroactivamente a los estándares de C++ publicados anteriormente.
| DR | Aplicado a | Comportamiento publicado | Comportamiento correcto |
|---|---|---|---|
| LWG 3 | C++98 |
durante la limpieza, el comportamiento no estaba claro cuando (1) una función está
registrada con std::atexit o (2) un objeto local estático es inicializado |
aclarado |
Véase también
|
provoca la terminación anormal del programa (sin limpieza)
(función) |
|
|
registra una función para ser llamada al invocar
std::exit()
(función) |
|
|
(C++11)
|
provoca la terminación rápida del programa sin limpieza completa
(función) |
|
(C++11)
|
registra una función para ser llamada al invocar
std::quick_exit
(función) |
|
Documentación de C
para
exit
|
|