Pregunta

¿Debo usar exit () o simplemente return declaraciones en main () ? Personalmente, estoy a favor de las declaraciones return porque siento que es como leer cualquier otra función y el control de flujo cuando leo el código es fluido (en mi opinión). E incluso si quiero refactorizar la función main () , tener return parece una mejor opción que exit () .

¿ exit () hace algo especial que return no hace?

¿Fue útil?

Solución

En realidad, hay una diferencia, pero es sutil. Tiene más implicaciones para C ++, pero las diferencias son importantes.

Cuando llamo a return en main () , se llamará a los destructores para mis objetos de ámbito local. Si llamo a exit () , no se llamará a ningún destructor para mis objetos de ámbito local. Vuelva a leer eso. exit () no regresa . Eso significa que una vez que lo llamo, no hay "backsies". Los objetos que haya creado en esa función no serán destruidos. A menudo, esto no tiene implicaciones, pero a veces lo hace, como cerrar archivos (¿seguramente desea que todos sus datos se vayan al disco?).

Tenga en cuenta que los objetos static se limpiarán incluso si llama a exit () . Finalmente, tenga en cuenta que si usa abort () , no se destruirán objetos. Es decir, no se llamarán a sus destructores objetos globales, objetos estáticos ni objetos locales.

Proceda con precaución al favorecer la salida sobre el retorno.

http://groups.google.com/group/gnu. gcc.help/msg/8348c50030cfd15a

Otros consejos

Otra diferencia: exit es una biblioteca estándar función, por lo que debe incluir encabezados y enlaces con el estándar biblioteca. Para ilustrar (en C ++), Este es un programa válido:

int main() { return 0; }

pero para usar exit necesitará incluir:

#include <stdlib.h>
int main() { exit(EXIT_SUCCESS); }

Además, esto agrega una suposición adicional: que llamar a exit desde main tiene los mismos efectos secundarios que devolver cero. Como otros han señalado, esto depende del tipo de ejecutable que esté construyendo (es decir, quién llama a main ). ¿Estás codificando una aplicación que usa el tiempo de ejecución C? ¿Un complemento maya? ¿Un servicio de Windows? ¿Un conductor? Cada caso requerirá investigación para ver si exit es equivalente a return . En mi humilde opinión, usar exit cuando realmente quieres decir return solo hace que el código sea más confuso. OTOH, si realmente quiere decir salir , entonces utilícelo.

Hay al menos un motivo para preferir exit : si alguno de sus controladores atexit se refiere a datos de duración de almacenamiento automático en main , o si usó setvbuf o setbuf para asignar a una de las transmisiones estándar un búfer de duración de almacenamiento automático en main , luego regresando de main produce un comportamiento indefinido, pero llamar a exit es válido.

Sin embargo, otro uso potencial (generalmente reservado para programas de juguetes) es salir de un programa con invocaciones recursivas de main .

Siempre uso return porque el prototipo estándar para main () dice que devuelve un int .

Dicho esto, algunas versiones de los estándares otorgan a main un tratamiento especial y suponen que devuelve 0 si no hay una declaración explícita de return . Dado el siguiente código:

int foo() {}
int main(int argc, char *argv[]) {}

G ++ solo genera una advertencia para foo () e ignora el retorno faltante de main :

% g++ -Wall -c foo.cc
foo.cc: In function ‘int foo()’:
foo.cc:1: warning: control reaches end of non-void function

I STRONGLY secundo el comentario de R. sobre el uso de exit () para evitar tener un almacenamiento automático en main () antes de que el programa realmente finalice. Una declaración return X; en main () no es exactamente equivalente a una llamada a exit (X); , ya que el almacenamiento dinámico de < code> main () desaparece cuando main () regresa, pero no desaparece si se realiza una llamada a exit () en su lugar.

Además, en C o en cualquier lenguaje similar a C, una instrucción return sugiere al lector que la ejecución continuará en la función de llamada, y si bien esta continuación de la ejecución suele ser técnicamente cierta si cuenta la rutina de inicio de C que llamó a su función main () , no es exactamente lo que usted quiere decir cuando quiere terminar el proceso.

Después de todo, si desea finalizar su programa desde cualquier otra función excepto main () debe debe llamar a exit () . Hacerlo de manera consistente en main () también hace que su código sea mucho más legible, y también hace que sea mucho más fácil para cualquier persona re-factorizar su código; es decir, el código copiado de main () a alguna otra función no se comportará mal debido a declaraciones accidentales de return que deberían haber sido exit ( ) llamadas.

Entonces, combinando todos estos puntos, la conclusión es que es un mal hábito , al menos para C, usar una instrucción return para finalizar el programa en < code> main () .

  

¿La salida () hace algo especial que 'return' no haga?

Con algunos compiladores para plataformas poco comunes, exit () podría traducir su argumento en el valor de salida de su programa, mientras que un retorno de main () podría pasar el valor directamente a el entorno host sin ninguna traducción.

El estándar requiere un comportamiento idéntico en estos casos (específicamente, dice que devolver algo que es int -compatible desde main () debería ser equivalente a llamar a exit ( ) con ese valor). El problema es que diferentes sistemas operativos tienen diferentes convenciones para interpretar los valores de salida. En muchos sistemas (¡MUCHOS!), 0 significa éxito y cualquier otra cosa es un fracaso. Pero en, por ejemplo, VMS, los valores impares significan éxito y los pares significan fracaso. Si devolvió 0 de main () , un usuario de VMS vería un mensaje desagradable sobre una infracción de acceso. En realidad no hubo una infracción de acceso, ese fue simplemente el mensaje estándar asociado con el código de falla 0.

Luego apareció ANSI y bendijo EXIT_SUCCESS y EXIT_FAILURE como argumentos que podría pasar a exit () . El estándar también dice que exit (0) debe comportarse de manera idéntica a exit (EXIT_SUCCESS) , por lo que la mayoría de las implementaciones definen EXIT_SUCCESS en 0 .

El estándar, por lo tanto, lo pone en un enlace en VMS, ya que no deja una forma estándar de devolver un código de falla que tiene el valor 0.

El compilador VAX / VMS C de principios de la década de 1990, por lo tanto, no interpretó el valor de retorno de main () , simplemente devolvió el valor al entorno del host. Pero si usó exit () haría lo que el estándar requería: traducir EXIT_SUCCESS (o 0 ) en un código de éxito y EXIT_FAILURE en un código de falla genérico. Para usar EXIT_SUCCESS , tenía para pasarlo a exit () , no podía devolverlo desde main () . No sé si las versiones más modernas de ese compilador conservaron ese comportamiento.

Un programa C portátil solía verse así:

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

int main() {
  printf("Hello, World!\n");
  exit(EXIT_SUCCESS);  /* to get good return value to OS */
  /*NOTREACHED*/ /* to silence lint warning */
  return 0;  /* to silence compiler warning */
}

Aparte: si recuerdo correctamente, la convención VMS para los valores de salida está más matizada que impar / par. En realidad, usa algo como los tres bits bajos para codificar un nivel de gravedad. En términos generales, sin embargo, los niveles de gravedad impares indicaron éxito o información diversa y los pares indicaron errores.

En C regresar de main es exactamente lo mismo que llamar a exit con el mismo valor.

Sección 5.1.2.2.3 del C estándar:

  

Si el tipo de retorno de la función principal es un tipo compatible con int   , un retorno de la llamada inicial a la función principal es equivalente a   llamando a la función de salida con el valor devuelto por el main   funcionar como argumento ; 11) alcanzar el} que termina el   La función principal devuelve un valor de 0. Si el tipo de retorno es   no es compatible con int, el estado de terminación regresó a   el entorno del host no está especificado.

Las reglas para C ++ son un poco diferentes como se menciona en otras respuestas.

En realidad, existe una diferencia entre exit (0) y return (0) en main & # 8211; & nbsp; cuando su < La función code> main se llama varias veces.

El siguiente programa

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

int main(int argc, char** argv) {
  if (argc == 0)
    return(0);
  printf("%d", main(argc - 1, argv));
}

Ejecutar como

./program 0 0 0 0

Producirá el siguiente resultado:

00000

Sin embargo, este:

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

int main(int argc, char** argv) {
  if (argc == 0)
    exit(0);
  printf("%d", main(argc - 1, argv));
}

No imprimirá nada independientemente de los argumentos.

Si está seguro de que nadie llamará a su main explícitamente, técnicamente no es una gran diferencia, pero mantener un código más claro exit se vería mucho mejor. Si por alguna razón desea llamar a main & # 8211; debes ajustarlo a tus necesidades.

Hablando de C.

Licenciado bajo: CC-BY-SA con atribución
No afiliado a StackOverflow
scroll top