2010-08-11 17 views

Respuesta

115
  • retorno 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 en el que tanto hacer (casi) lo mismo es en la función main(), como un retorno de la principal 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 se ejecuta este programa imprime:

Executing f 
Back from f 

Otro ejemplo de exit():

#include <stdio.h> 
#include <stdlib.h> 

void f(){ 
    printf("Executing f\n"); 
    exit(0); 
} 

int main(){ 
    f(); 
    printf("Back from f\n"); 
} 

Si se ejecuta este programa se imprime:

Executing f 

Nunca se obtiene "A la vuelta de f". También observe el #include <stdlib.h> necesario para llamar a la función de biblioteca exit().

Observe también que el parámetro exit() es un número entero (es el estado de retorno del proceso que puede obtener el proceso de 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.

El último punto, exit() viene en dos sabores _exit() y exit(). La diferencia entre los formularios es que exit() (y devolver desde el principal) llama a las funciones registradas usando atexit() o on_exit() antes de terminar realmente el proceso mientras _exit() (de #include <unistd.h>, o su _Salida de #include <stdlib.h>) finaliza 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 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, el C++ OStream creado 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 las antiguas y buenas secuencias de C FILE*. Se eliminarán en el exit(). En realidad, la regla es la misma que para las funciones de salida registradas, FILE* se purgará en todas las terminaciones normales, que incluyen 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 será call 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án los destructores de objetos C++ estáticos (globales) si llama return desde main() o exit() desde cualquier lugar de su programa. No se llamarán si el programa finaliza usando _exit() o abort(). abort() es principalmente útil en el modo de depuración con el fin 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 el usuario de la biblioteca debería elegir implementar algún tipo de recuperación de errores o no. Si desea un ejemplo de por qué llamar a exit() desde una biblioteca es malo, lleva, por ejemplo, a personas a preguntar this question.

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.

+6

salida() no es una llamada al sistema –

+0

@anon: tiene razón, técnicamente es un retorno al sistema, pero no hay mucha diferencia. – kriss

+0

@JonathanLeffler En 'main()' se prefiere usar 'return' o' exit'? Busque el código de ejemplo [THIS] (https://gist.github.com/anonymous/c293fbd346a534912e69). –

10

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 comenzó su programa, que a su vez llama a exit() de todos modos. Entonces realmente no importa cuál usas.

+1

Sí importa. exit() finaliza inmediatamente el programa, sin importar dónde se llame. return solo sale de la función actual. la única ubicación en la que hacen lo mismo es en main() – Amy

+0

Gracias, he corregido la redacción. No es necesariamente solo en main(), ya que no todos los compiladores usan el mismo nombre de función para la función de inicio. –

+7

Supongo que escribes todos tus programas en una gran función principal. ;-) –

13

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 la asamblea (sólo 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: return utilizan cuando se puede, y exit() cuando se necesita.

1

las salidas de los estados de retorno de la función actual y la salida() sale del programa

they are the same when used in main() function 

también de retorno es una declaración, mientras que la salida() es una función que requiere el archivo de cabecera stdlb.h

Cuestiones relacionadas