son - ¿Cuál es la diferencia entre salir y regresar?
diferencias culturales entre mexico y estados unidos (4)
Esta pregunta ya tiene una respuesta aquí:
- return statement vs exit () en main () 6 respuestas
¿Cuál es la diferencia entre declaración de retorno y de salida en la programación C cuando se llama desde cualquier lugar en un programa C?
En C, no hay mucha diferencia cuando se usa en la función de inicio del programa (que puede ser main()
, wmain()
, _tmain()
o el nombre predeterminado utilizado por el compilador).
Si return
en main()
, el control vuelve a la función _start()
en la biblioteca C que originalmente inició su programa, que luego llama a exit()
todos modos. Entonces realmente no importa cuál usas.
Escribí dos programas:
int main(){return 0;}
y
#include <stdlib.h>
int main(){exit(0)}
Después de ejecutar gcc -S -O1
. Aquí lo que encontré viendo en el ensamblaje (solo partes importantes):
main:
movl $0, %eax /* setting return value */
ret /* return from main */
y
main:
subq $8, %rsp /* reserving some space */
movl $0, %edi /* setting return value */
call exit /* calling exit function */
/* magic and machine specific wizardry after this call */
Así que mi conclusión es: use return
cuando pueda y exit()
cuando lo necesite.
la declaración de devolución sale de la función actual y sale () del programa
they are the same when used in main() function
también return es una declaración mientras que exit () es una función que requiere el archivo stdlb.h header
- return es una instrucción del lenguaje que regresa de una llamada de función.
- exit es una llamada al sistema (no una declaración de idioma) que finaliza el proceso actual.
El único caso cuando ambos hacen (casi) lo mismo está en la función main()
, ya que un retorno desde main realiza una exit()
.
Ejemplo con return
:
#include <stdio.h>
void f(){
printf("Executing f/n");
return;
}
int main(){
f();
printf("Back from f/n");
}
Si ejecuta este programa imprime:
Executing f Back from f
Otro ejemplo para exit()
:
#include <stdio.h>
#include <stdlib.h>
void f(){
printf("Executing f/n");
exit(0);
}
int main(){
f();
printf("Back from f/n");
}
Si ejecuta este programa imprime:
Executing f
Nunca se obtiene "Atrás de f". También observe el #include <stdlib.h>
necesario para llamar a la función de biblioteca exit()
.
También tenga en cuenta que el parámetro de exit()
es un entero (es el estado de retorno del proceso que puede obtener el proceso del iniciador, el uso convencional es 0 para el éxito o cualquier otro valor para un error).
El parámetro de la instrucción return es cualquiera que sea el tipo de retorno de la función. Si la función devuelve vacío, puede omitir el retorno al final de la función.
Último punto, exit()
viene en dos sabores _exit()
y exit()
. La diferencia entre los formularios es que exit()
(y return from main) llama a las funciones registradas usando atexit()
o on_exit()
antes de terminar realmente el proceso mientras _exit()
(from #include <unistd.h>
, o su _Salir from #include <stdlib.h>
) finaliza el proceso de inmediato.
Ahora también hay problemas que son específicos de C ++.
C ++ realiza mucho más trabajo que C cuando sale de funciones ( return
-ing). Específicamente llama a los destructores de objetos locales fuera del alcance. En la mayoría de los casos, los programadores no se preocuparán mucho por el estado de un programa una vez que se haya detenido el proceso, por lo tanto, no habrá mucha diferencia: se liberará la memoria asignada, se cerrará el recurso de archivo y así sucesivamente. Pero puede importar si su destructor realiza IO. Por ejemplo, la OStream
automática de C ++ OStream
creada localmente no se descargará en una llamada para salir y puede perder algunos datos no eliminados (por otro lado, se descargará el OStream
estático).
Esto no sucederá si está utilizando los buenos viejos FILE*
C FILE*
. Estos se purgarán en la exit()
. En realidad, la regla es la misma que para las funciones de salida registradas, FILE*
se vaciará en todas las terminaciones normales, lo que incluye exit()
, pero no llamadas a _exit()
o abort ().
También debe tener en cuenta que C ++ proporciona una tercera forma de salir de una función: lanzar una excepción. Esta forma de salir de una función llamará a destructor. Si no está atrapado en ninguna parte de la cadena de llamadas, la excepción puede ir a la función main () y finalizar el proceso.
Se invocará a los destruidores de objetos estáticos de C ++ (globales) si llama a return
from main()
o exit()
en cualquier parte de su programa. No se _exit()
si el programa finaliza usando _exit()
o abort()
. abort()
es principalmente útil en el modo de depuración con el propósito de detener inmediatamente el programa y obtener un seguimiento de la pila (para el análisis post mortem). Por lo general, se oculta detrás de la macro assert()
solo activa en el modo de depuración.
¿Cuándo es útil exit ()?
exit()
significa que desea detener inmediatamente el proceso actual. Puede ser de alguna utilidad para la gestión de errores cuando nos encontramos con algún tipo de problema irrecuperable que no permitirá que su código haga algo útil. A menudo es útil cuando el flujo de control es complicado y los códigos de error deben propagarse hacia arriba. Pero ten en cuenta que esta es una mala práctica de codificación. En la mayoría de los casos, finalizar el proceso silenciosamente es el peor comportamiento y la gestión de errores real debe preferirse (o en C ++ con excepciones).
Las llamadas directas a exit()
son especialmente malas si se realizan en bibliotecas, ya que condenarán al usuario de la biblioteca y la elección del usuario de la biblioteca debería ser implementar algún tipo de recuperación de error o no. Si desea un ejemplo de por qué llamar a exit()
desde una biblioteca es malo, lleva, por ejemplo, a personas a hacer esta pregunta .
Existe un uso legítimo indiscutible de exit()
como la forma de finalizar un proceso hijo iniciado por fork () en los sistemas operativos que lo soportan. Volver al código antes de tenedor () suele ser una mala idea. Este es el razonamiento que explica por qué las funciones de la familia exec () nunca regresarán a la persona que llama.