En realidad, no es una diferencia, pero es sutil. Tiene más implicaciones para C ++, pero las diferencias son importantes.
Cuando llamo , se llamarán return
a los main()
destructores para mis objetos de ámbito local. Si llamo exit()
, no se llamará a destructor para mis objetos localmente alcanzados. Vuelve a leer eso. exit()
no vuelve . 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 vacíen en el disco?).
Tenga en cuenta que los static
objetos se limpiarán incluso si llama 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
thread_local
que se llamará a los destructores de objetos. Los destructores de otros objetos locales todavía no se llaman. ideone.com/Y6Dh3fexit()
cerrar los archivos limpiamente es realmente incorrecto. El único momento en que los datos podrían no vaciarse es en el caso opuesto: es decir, si uno usareturn
desdemain()
y ha llamadosetbuf()
osetvbuf()
con un búfer declarado como almacenamiento automático enmain()
(como se discute en la respuesta de R. a continuación). Es realmente una lástima que esta pregunta esté etiquetada con C y C ++ (y con estilo de codificación, ¡no es un problema de estilo!).Otra diferencia:
exit
es una función de biblioteca estándar, por lo que debe incluir encabezados y enlaces con la biblioteca estándar. Para ilustrar (en C ++), este es un programa válido:pero para usar
exit
necesitarás incluir:Además, esto agrega una suposición adicional: que llamar
exit
desdemain
tiene los mismos efectos secundarios que devolver cero. Como otros han señalado, esto depende de qué tipo de ejecutable esté construyendo (es decir, quién llamamain
). ¿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 siexit
es equivalente areturn
. En mi humilde opinión, usarexit
cuando realmente te refieresreturn
solo hace que el código sea más confuso. OTOH, si realmente quieres decirexit
, entonces utilízalo .fuente
Hay al menos una razón para preferir
exit
: si alguno de susatexit
controladores se refiere a datos de duración de almacenamiento automáticomain
, o si usósetvbuf
osetbuf
asignó a una de las transmisiones estándar un búfer de duración de almacenamiento automáticomain
, luego regresa demain
produce comportamiento indefinido, pero la llamadaexit
es válida.Sin embargo, otro uso potencial (generalmente reservado para programas de juguetes) es salir de un programa con invocaciones recursivas de
main
.fuente
main()
: es solo una función como cualquier otra. Por otro lado, dado que tiene una mención especial en el estándar, el estándar debe ser bastante cuidadoso acerca de cómo se definemain()
y las cosas cercanas y queridas. Sin embargo, al final, el estándar no requiere (y no debe ) que los compiladores hagan algo especial sobre el almacenamiento automáticomain()
. Lea atentamente la Nota al pie # 11 debajo del párrafo al que hizo referencia en su comentario.Siempre uso
return
porque el prototipo estándar paramain()
dice que devuelve unint
.Dicho esto, algunas versiones de los estándares dan
main
un tratamiento especial y suponen que devuelve 0 si no hay unareturn
declaración explícita . Dado el siguiente código:G ++ solo genera una advertencia
foo()
e ignora el retorno faltante demain
:fuente
return
para finalizar su ejecución. Llamarexit()
también es una forma válida, y a veces necesaria, de finalizar la ejecución de cualquier función. De hecho, como yo y otros hemos descrito en otra parte, llamarexit()
incluso desdemain()
transmite una intención mucho más clara de salir de todo el proceso, preserva el almacenamiento automático hasta la salida del proceso y facilita el mantenimiento durante la futura refactorización del código. Para C usarreturn
inmain()
cuando la intención es terminar el proceso es, por lo tanto, una mala práctica.I ENÉRGICAMENTE segundo el comentario de R. acerca del uso de la salida () con el fin de evitar tener almacenamiento automático en
main()
recuperada antes de que el programa realmente extremos. Unareturn X;
declaración enmain()
no es exactamente equivalente a una llamada aexit(X);
, ya que el almacenamiento dinámico demain()
desaparece cuandomain()
regresa, pero no desaparece si se realiza una llamada aexit()
.Además, en C o en cualquier lenguaje similar a C, una
return
declaración 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 sumain()
función, no es exactamente lo que quieres decir cuando quieres terminar el proceso.Después de todo, si usted desea terminar su programa desde cualquier otra función, excepto
main()
que debe llamarexit()
. Hacerlo de manera consistentemain()
también hace que su código sea mucho más legible, y también hace que sea mucho más fácil para cualquiera volver a factorizar su código; es decir, el código copiado demain()
alguna otra función no se comportará mal debido areturn
declaraciones accidentales que deberían haber sidoexit()
llamadas.Entonces, combinando todos estos puntos, la conclusión es que es un mal hábito , al menos para C, usar una
return
declaración para finalizar el programamain()
.fuente
exit()
en general, pero lo uso si unathrow
o otrasabort()
alternativas no funcionan en un contexto específico. Pero especialmente eviteexit()
en main, y use return en main en su lugar como práctica típica.Con algunos compiladores para plataformas poco comunes,
exit()
podría traducir su argumento al valor de salida de su programa, mientras que un retorno demain()
podría simplemente pasar el valor directamente al entorno host sin ninguna traducción.El estándar requiere un comportamiento idéntico en estos casos (específicamente, dice que devolver algo que sea
int
compatiblemain()
debería ser equivalente a llamarexit()
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 desdemain()
, 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, ANSI apareció y fue bendecido
EXIT_SUCCESS
yEXIT_FAILURE
como argumentos a los que podrías pasarexit()
. La norma también dice queexit(0)
debe comportarse de forma idéntica aexit(EXIT_SUCCESS)
, por lo que la mayoría de las implementaciones definenEXIT_SUCCESS
a0
.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
main()
, simplemente devolvió cualquier valor al entorno host. Pero si lo usaraexit()
, haría lo que el estándar requería: traducirEXIT_SUCCESS
(o0
) en un código de éxito yEXIT_FAILURE
en un código de falla genérico. Para usarloEXIT_SUCCESS
, tenía que pasárseloexit()
, no podía devolverlomain()
. No sé si las versiones más modernas de ese compilador conservaron ese comportamiento.Un programa C portátil solía verse así:
Aparte: si recuerdo correctamente, la convención VMS para valores de salida tiene más matices 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 variada y los pares indicaron errores.
fuente
returned
de maneramain
diferente del valor pasado aexit
, pero el estándar dice específicamente: "Si el tipo de retorno de lamain
función es un tipo compatible conint
, un retorno de la llamada inicial a lamain
función es equivalente a llamar a laexit
función con el valor devuelto por lamain
función como argumento ". Eso es C11; C89 / C90 tenía casi la misma redacción.EXIT_SUCCESS
, no había forma de devolver un estado de falla específico de la plataforma con el valor 0, por lo que algunos de los compiladores de la era trataron el retorno desde el principal Yexit()
diferente.En C regresar de
main
es exactamente lo mismo que llamarexit
con el mismo valor.La sección 5.1.2.2.3 de los estados estándar de C :
Las reglas para C ++ son un poco diferentes como se menciona en otras respuestas.
fuente
En realidad, existe una diferencia entre
exit(0)
yreturn(0)
enmain
- cuando sumain
función se llama varias veces.El siguiente programa
Correr como
Resultará en la siguiente salida:
Sin embargo este:
No imprimirá nada independientemente de los argumentos.
Si está seguro de que nadie lo llamará
main
explícitamente, técnicamente no es una gran diferencia en general, pero mantener un código más claroexit
se vería mucho mejor. Si por alguna razón desea llamarmain
, debe ajustarlo a sus necesidades.Hablando de C.
fuente