¿Cuál es la diferencia entre salir y volver?

¿Cuál es la diferencia entre las declaraciones de retorno y salida en la progtwigción en C cuando se llama desde cualquier lugar en un progtwig en C?

  • return es una instrucción del idioma que regresa de una llamada de función.
  • exit es una llamada del sistema (no una statement de idioma) que termina el proceso actual.

El único caso cuando ambos hacen (casi) lo mismo es en la función main() , ya que un retorno desde main realiza una exit() .

Ejemplo con return :

 #include  void f(){ printf("Executing f\n"); return; } int main(){ f(); printf("Back from f\n"); } 

Si ejecutas este progtwig se imprime:

 Executing f Back from f 

Otro ejemplo para exit() :

 #include  #include  void f(){ printf("Executing f\n"); exit(0); } int main(){ f(); printf("Back from f\n"); } 

Si ejecutas este progtwig se imprime:

 Executing f 

Nunca se obtiene “Back from f”. Observe también el #include necesario para llamar a la función de biblioteca exit() .

También tenga en cuenta que el parámetro 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 statement de retorno 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 _exit() y exit() . La diferencia entre los formularios es que exit() (y regresar desde main) llama a las funciones registradas usando atexit() o on_exit() antes de finalizar realmente el proceso mientras _exit() (de #include , o su sinónimo _Exit de #include ) termina el proceso inmediatamente.

Ahora también hay problemas que son específicos de C ++.

C ++ realiza mucho más trabajo que C cuando sale de las funciones ( return -ing). Específicamente se llama destructores de objetos locales que salen de ámbito. En la mayoría de los casos, a los progtwigdores no les importará mucho el estado de un progtwig después de que el proceso se haya detenido, por lo tanto, no haría mucha diferencia: la memoria asignada se liberará, el recurso del archivo se cerrará, etc. Pero puede importar si tu destructor realiza IOs. Por ejemplo, el C ++ OStream automático creado localmente no se eliminará en una llamada para salir y es posible que pierda algunos datos sin vaciar (por otro lado, el OStream estático se OStream ).

Esto no sucederá si está utilizando las buenas secuencias C FILE* antiguas. Estos serán eliminados en la exit() . En realidad, la regla es la misma que para las funciones de salida registradas, el FILE* borrará en todas las terminaciones normales, lo que incluye la exit() , pero no las 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á destructor. Si no está atrapado en ninguna parte de la cadena de llamantes, la excepción puede ir a la función main () y terminar el proceso.

Se llamarán los destructores de objetos C ++ estáticos (globales) si llama a return desde main() o exit() en cualquier parte de su progtwig. No se _exit() si el progtwig finaliza con _exit() o abort() . abort() es principalmente útil en el modo de depuración con el propósito de detener inmediatamente el progtwig y obtener un seguimiento de la stack (para el análisis post mortem). Por lo general, se oculta detrás de la macro assert() solo activa en 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 nada útil. A menudo es útil cuando el flujo de control es complicado y los códigos de error deben propagarse completamente. Pero ten en cuenta que esta es una mala práctica de encoding. La finalización silenciosa del proceso es, en la mayoría de los casos, el peor comportamiento y se debería preferir la administración de errores reales (o en C ++ con excepciones).

Las llamadas directas a exit() son especialmente malas si se realizan en las bibliotecas, ya que condenarán al usuario de la biblioteca y debería ser una opción de los usuarios de la biblioteca implementar algún tipo de recuperación de errores o no. Si desea un ejemplo de por qué es incorrecto llamar a exit() desde una biblioteca, por ejemplo, las personas hacen esta pregunta .

Existe un uso legítimo indiscutible de exit() como la forma de finalizar un proceso secundario iniciado por fork () en los sistemas operativos que lo admiten. Volver al código antes de fork () 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.

Escribí dos progtwigs:

 int main(){return 0;} 

y

 #include  int main(){exit(0)} 

Después de ejecutar gcc -S -O1 . Aquí lo que encontré viendo en la asamblea (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.

En C, no hay mucha diferencia cuando se usa en la función de inicio del progtwig (que puede ser main() , wmain() , _tmain() o el nombre predeterminado usado por su comstackdor).

Si return en main() , el control vuelve a la función _start() en la biblioteca C que originalmente inició su progtwig, que luego llama a exit() todos modos. Así que realmente no importa cuál uses.

la instrucción de retorno sale de la función actual y exit () sale del progtwig

 they are the same when used in main() function 

también return es una statement, mientras que exit () es una función que requiere el archivo de encabezado stdlb.h