En C y C++, ¿cuál es la diferencia entre exit()
y abort()
? Estoy tratando de finalizar mi programa después de un error (no una excepción).¿Cuál es la diferencia entre exit() y abort()?
Respuesta
aborto envía una señal SIGABRT, salida simplemente cierra la aplicación que realiza la limpieza normal.
Puede manejar una señal abortar como quiera, pero el comportamiento predeterminado es cerrar la aplicación también con un código de error.
abortar no llevará a cabo la destrucción de objetos de sus miembros estáticos y globales, pero salida voluntad.
Sin embargo, cuando la aplicación está completamente cerrada, el sistema operativo liberará cualquier memoria no liberada y otros recursos.
En tanto abortar y salida la terminación del programa (asumiendo que no anular el comportamiento por defecto), el código de retorno será devuelto al proceso padre que se inició su aplicación.
Véase el siguiente ejemplo:
SomeClassType someobject;
void myProgramIsTerminating1(void)
{
cout<<"exit function 1"<<endl;
}
void myProgramIsTerminating2(void)
{
cout<<"exit function 2"<<endl;
}
int main(int argc, char**argv)
{
atexit (myProgramIsTerminating1);
atexit (myProgramIsTerminating2);
//abort();
return 0;
}
Comentarios:
Si abortar es sin comentar: nada se imprime y el destructor de someObject no será llamado.
Si abortar se comenta como la de arriba: destructor someObject se llamará obtendrá el siguiente resultado:
función de salida 2
función de salida 1
abort()
sale de su programa sin llamar primero a las funciones registradas usando atexit()
, y sin llamar a los objetos 'de primero los estructores. exit()
hace ambas cosas antes de salir de su programa. Sin embargo, no llama destructores para objetos automáticos. Así
A a;
void test() {
static A b;
A c;
exit(0);
}
destruyan a
y b
correctamente, pero no va a llamar a los destructores de c
. abort()
no llamaría a destructores de ninguno de los objetos. Como esto es lamentable, el estándar de C++ describe un mecanismo alternativo que garantiza adecuadamente la terminación:
Los objetos con una duración de almacenamiento automático están todos destruidos en un programa cuya función
main()
no contiene objetos automáticos y ejecuta la llamada aexit()
. El control se puede transferir directamente a unmain()
lanzando una excepción que se captura enmain()
.
struct exit_exception {
int c;
exit_exception(int c):c(c) { }
};
int main() {
try {
// put all code in here
} catch(exit_exception& e) {
exit(e.c);
}
}
En lugar de llamar exit()
, disponer que el código throw exit_exception(exit_code);
lugar.
+1 porque, mientras Brian R.Bondy fue bueno, planteó el problema de abortar/salir (no se llamó el destructor de los objetos de la pila), y ofreció la alternativa para un proceso de C++ intensivo en RAII. – paercebal
¡Estaba buscando una forma de salir de un programa sin llamar a dtor y su respuesta es justamente lo que estaba buscando! Gracias – acemtp
Eso es perfectamente correcto, por supuesto, si realmente importa que sus objetos automáticos no se llamen destructores :-) –
abort
envía la señal SIGABRT
. abort
no regresa a la persona que llama. El controlador predeterminado para la señal SIGABRT
cierra la aplicación. stdio
las transmisiones de archivos se lavan y luego se cierran. Sin embargo, los destructores para instancias de clase C++ no lo son (no estoy seguro de esto, ¿quizás los resultados no están definidos?).
exit
tiene sus propias devoluciones de llamadas, establecidas con atexit
. Si se especifican las devoluciones de llamada (o solo una), se llaman en el orden inverso de su orden de registro (como una pila), y luego sale el programa. Al igual que con abort
, exit
no regresa a la persona que llama. stdio
las transmisiones de archivos se lavan y luego se cierran. Además, se invocan destructores para instancias de clase C++.
exit puede tener múltiples funciones de devolución de llamada registradas a través de atexit, cuando se llama a exit todas las funciones de devolución de llamada se invocarán en el orden inverso en el que se registraron. –
@Gamble, por supuesto, lo mencioné hace unos minutos en un comentario a la respuesta de @ Bondy. Editaré mi propia respuesta para reflejar eso. – strager
Desde la página del manual de salida():
La función exit() hace que la terminación del proceso normal y el valor de estado & 0377 se devuelve a los padres.
Desde la página del manual de aborto():
El aborto() desbloquea primero la señal SIGABRT, y luego plantea que señal para el proceso de llamada. Esto da como resultado la terminación anómala del proceso, a menos que se capte la señal SIGABRT y el manejador de la señal no regrese.
Los siguientes cosas ocurren cuando un programa llama exit
():
- funciones registradas por la función
atexit
se ejecutan - Todos los flujos abiertos se vacían y se cierran, los archivos creados por
tmpfile
se eliminan - El programa finaliza con el código de salida especificado en el host
La función abort
() envía la señal al proceso actual, si no se captura el programa finaliza sin garantía de que las secuencias abiertas se descargan o cierran o que los archivos temporales creados a través de tmpfile
se eliminan, las funciones registradas atexit
no se llaman y se devuelve un estado de salida distinto de cero al host.
hmm. el estándar dice que el programa solo no finaliza si el manejador de señal "no regresa". estás bastante bien con C. ¿te imaginas cualquier escenario que lo haga permitir continuar la ejecución normal sin volver? me imagino longjmp, pero no estoy seguro de cómo se comporta en los controladores de señal. –
En general, llamar longjmp desde un manejador de señal no está definido, pero hay un caso especial para cuando la señal se generó con raise/abort así que supongo que esto sería teóricamente posible aunque no creo haberlo visto nunca. Ahora voy a tener que probarlo;) –
Esto parece funcionar (dividido en varios mensajes debido a 300 límite char): # include # include
- 1. Cuando abort() es preferible a exit()?
- 2. Diferencia entre exit() y sys.exit() en Python
- 3. Cuál es la diferencia entre echo ('exit'); morir; y morir ('salir');?
- 4. ¿Cuál es la diferencia entre {0} y ""?
- 5. Cuál es la diferencia entre = y: =
- 6. ¿Cuál es la diferencia entre .ToString (+) y ""
- 7. Cuál es la diferencia entre $ (...) y `...`
- 8. ¿cuál es la diferencia entre:.! y: r !?
- 9. ¿Cuál es la diferencia entre ".equals" y "=="?
- 10. ¿Cuál es la diferencia entre dict() y {}?
- 11. ¿Cuál es la diferencia entre `##` y `hashCode`?
- 12. ¿Cuál es la diferencia entre "$^N" y "$ +"?
- 13. ¿Cuál es la diferencia entre [indefinido] y [,]?
- 14. ¿Cuál es la diferencia entre + = y = +?
- 15. ¿Cuál es la diferencia entre " " y ""?
- 16. Cuál es la diferencia entre $ y jQuery
- 17. Diferencia entre java 'assert' y 'if() {} else exit;'
- 18. ¿Cuál es la diferencia entre std :: quick_exit y std :: abort y por qué se necesitó std :: quick_exit?
- 19. Python: ¿Cuál es la diferencia entre __builtin__ y __builtins__?
- 20. ¿Cuál es la diferencia entre Ctrl-C y SIGINT?
- 21. OpenGL (ES) - ¿Cuál es la diferencia entre frustum y orto?
- 22. Cuál es la diferencia entre la función() {}() y la función() {}()
- 23. ¿Cuál es la diferencia entre la abstracción y la encapsulación?
- 24. ¿Cuál es la diferencia entre @ y $ y% en MSBuild?
- 25. ¿Cuál es la diferencia entre la vinculación estática y dinámica?
- 26. ¿Cuál es la diferencia entre la sección .got y .got.plt?
- 27. ¿Cuál es la diferencia entre el colado y la coerción?
- 28. ¿cuál es la diferencia entre el complemento y la biblioteca?
- 29. ¿Cuál es la diferencia entre el casting y la conversión?
- 30. ¿Cuál es la diferencia entre WPF y la aplicación Silverlight?
Aquí, se llama función de salida 2 THEN exit function 1. gcc 4, Linux 2.6. – strager
La página del manual para atexit dice: "Las funciones [registradas usando atexit] se llaman en orden inverso, no se pasan argumentos". – strager
@strager tiene razón, se supone que las funciones registradas por atexit se invocan en orden inverso cuando se llama exit o return principal. –