Me gustaría que mi código C ++ deje de ejecutarse si se cumple una determinada condición, pero no estoy seguro de cómo hacerlo. Entonces, en cualquier momento, si una if
declaración es verdadera, finalice el código de esta manera:
if (x==1)
{
kill code;
}
main()
retorno de uso, en funciones use un valor de retorno adecuado o arroje una Excepción adecuada. No lo useexit()
!NDEBUG
definido,assert
probablemente se convertirá en un no-op, por lo que no debe confiar en él para más que detectar errores.return
frommain()
es perfectamente lógico. Establece el código de salida informado por el programa para el sistema operativo, que puede ser útil en muchos casos (si su programa se puede usar como parte de un proceso más grande, por ejemplo).exit()
considera malo? - SO 25141737 y ¿Cómo salir de un programa C ++? - SO 1116493 ahora están cerrados como duplicados de este. El primero de ellos tiene una referencia al 'Software solo para accidentes' que podría valer la pena, aunque solo sea para estimular su pensamiento sobre cómo escribir un software robusto.Respuestas:
Hay varias formas, pero primero debe comprender por qué la limpieza de objetos es importante y, por lo tanto, la razón
std::exit
está marginada entre los programadores de C ++.RAII y Desbobinado de pila
C ++ utiliza un idioma llamado RAII , que en términos simples significa que los objetos deben realizar la inicialización en el constructor y la limpieza en el destructor. Por ejemplo, la
std::ofstream
clase [puede] abrir el archivo durante el constructor, luego el usuario realiza operaciones de salida en él y, finalmente, al final de su ciclo de vida, generalmente determinado por su alcance, se llama al destructor que esencialmente cierra el archivo y descarga cualquier contenido escrito en el disco.¿Qué sucede si no llega al destructor para vaciar y cerrar el archivo? ¡Quién sabe! Pero posiblemente no escribirá todos los datos que se suponía que debía escribir en el archivo.
Por ejemplo, considere este código
Lo que sucede en cada posibilidad es:
os
llamar así a su destructor y realizar una limpieza adecuada al cerrar y vaciar el archivo al disco.inner_mad
, el desbobinador pasará por la pila demad
ymain
para realizar la limpieza adecuada, todos los objetos se destruirán correctamente, incluidosptr
yos
.exit
es una función de C y no es consciente ni compatible con los modismos de C ++. Que no se realice la limpieza de sus objetos, incluyendoos
en el mismo ámbito. Por lo tanto, su archivo no se cerrará correctamente y, por esta razón, ¡es posible que el contenido nunca se escriba en él!return 0
y, por lo tanto, tendrá el mismo efecto que la posibilidad 1, es decir, una limpieza adecuada.Pero no esté tan seguro de lo que le acabo de decir (principalmente las posibilidades 2 y 3); continúe leyendo y descubriremos cómo realizar una limpieza adecuada basada en excepciones.
Posibles formas de terminar
Regreso de la principal!
Debe hacer esto siempre que sea posible; siempre prefiera regresar de su programa devolviendo un estado de salida adecuado de main.
La persona que llama de su programa, y posiblemente el sistema operativo, puede querer saber si lo que su programa debía hacer se realizó con éxito o no. Por esta misma razón, debe devolver cero o
EXIT_SUCCESS
para indicar que el programa finalizó correctamente yEXIT_FAILURE
para indicar que el programa finalizó sin éxito, cualquier otra forma de valor de retorno está definida por la implementación ( §18.5 / 8 ).Sin embargo, puede ser muy profundo en la pila de llamadas, y devolver todo puede ser doloroso ...
[No] lanzar una excepción
Lanzar una excepción llevará a cabo la limpieza adecuada del objeto utilizando el desbobinado de la pila, llamando al destructor de cada objeto en cualquier ámbito anterior.
Pero aquí está el truco ! Está definido por la implementación si el desbobinado de la pila se realiza cuando una excepción lanzada no se maneja (mediante la cláusula catch (...)) o incluso si tiene una
noexcept
función en el medio de la pila de llamadas. Esto se establece en §15.5.1 [excepto.terminal] :¡Entonces tenemos que atraparlo!
¡Lanza una excepción y atrapala en main!
Dado que las excepciones no detectadas pueden no realizar el desbobinado de la pila (y, en consecuencia, no realizarán la limpieza adecuada) , debemos detectar la excepción en main y luego devolver un estado de salida (
EXIT_SUCCESS
oEXIT_FAILURE
).Entonces, una configuración posiblemente buena sería:
[No] std :: salir
Esto no realiza ningún tipo de desbobinado de la pila, y ningún objeto vivo en la pila llamará a su respectivo destructor para realizar la limpieza.
Esto se aplica en §3.6.1 / 4 [basic.start.init] :
Piénsalo ahora, ¿por qué harías tal cosa? ¿Cuántos objetos has dañado dolorosamente?
Otras alternativas [como malas]
Hay otras formas de finalizar un programa (que no sean fallas) , pero no se recomiendan. Solo en aras de una aclaración, se presentarán aquí. Observe cómo la finalización normal del programa no significa el desenrollado de la pila, sino un estado correcto para el sistema operativo.
std::_Exit
provoca una terminación normal del programa, y eso es todo.std::quick_exit
provoca una finalización normal del programa y llama a losstd::at_quick_exit
controladores, no se realiza ninguna otra limpieza.std::exit
provoca una finalización normal del programa y luego llama a losstd::atexit
controladores. Se realizan otros tipos de limpieza, como llamar a destructores de objetos estáticos.std::abort
provoca una terminación anormal del programa, no se realiza ninguna limpieza. Esto debería llamarse si el programa terminó de una manera muy, muy inesperada. No hará nada más que indicarle al sistema operativo sobre la terminación anormal. Algunos sistemas realizan un volcado de núcleo en este caso.std::terminate
llama a las llamadasstd::terminate_handler
questd::abort
por defecto.fuente
new
lanzamientosstd::bad_alloc
y su programa olvidó detectar esa excepción en cualquier lugar) no desenrollará correctamente la pila antes de finalizar. Esto parece tonto a mí: que hubiera sido fácil esencialmente envolver la llamada amain
un trivialtry{
-}catch(...){}
bloque que aseguraría pila desenrollar se hace correctamente en estos casos, sin costo (y me refiero a: programas que no utilizan este no pagará multa). ¿Hay alguna razón en particular para que esto no se haga?std::abort
lugar para que el sistema operativo pueda liberar toda la memoria, los sockets y los descriptores de archivos sin cambiar por un minuto.Como Martin York mencionó, la salida no realiza la limpieza necesaria como lo hace el retorno.
Siempre es mejor usar return en el lugar de salida. En caso de que no esté en main, donde quiera salir del programa, regrese primero a main.
Considere el siguiente ejemplo. Con el siguiente programa, se creará un archivo con el contenido mencionado. Pero si return es comentado y no comentado exit (0), el compilador no le asegura que el archivo tendrá el texto requerido.
No solo esto, tener múltiples puntos de salida en un programa hará que la depuración sea más difícil. Use exit solo cuando pueda justificarse.
fuente
return (EXIT_SUCCESS);
lugarreturn(0)
Llama a la
std::exit
función.fuente
exit()
cuando el código de su biblioteca se esté ejecutando dentro de mi proceso de host; este último se cerrará en el medio de la nada.La gente dice "salida de llamada (código de retorno)", pero esta es una mala forma. En programas pequeños está bien, pero hay una serie de problemas con esto:
Realmente, la única vez que debe salir del problema es con esta línea en main.cpp:
Si está utilizando exit () para manejar errores, debe conocer las excepciones (y las excepciones de anidación), como un método mucho más elegante y seguro.
fuente
return 0;
ponlo donde quieras dentroint main()
y el programa se cerrará inmediatamente.fuente
main
.int main()
es diferente. El programa usaint main()
para comenzar y terminar. No hay otra forma de hacerlo. El programa se ejecutará hasta que devuelva verdadero o falso. Casi todo el tiempo devolverá 1 o verdadero, para indicar que el programa se ha cerrado correctamente (por ejemplo: podría usar falso si no puede liberar memoria o cualquier otra razón). Dejar que el programa se ejecute terminado siempre es una mala idea, por ejemplo:int main() { int x = 2; int foo = x*5; std::cout << "blah"; }
int main
; sin embargo, no siempre es una buena idea tener múltiples declaraciones de retorno en una rutina principal. Una advertencia potencial es mejorar la legibilidad del código; sin embargo, usar algo como una bandera booleana que cambia de estado para evitar que ciertas secciones de código se ejecuten en ese estado de aplicación. Personalmente, creo que una declaración de devolución común hace que la mayoría de las aplicaciones sean más legibles. Por último, preguntas sobre la limpieza de memoria y el cierre de objetos de E / S correctamente antes de la salida.true
amain
indicar una terminación correcta. Debe devolver cero oEXIT_SUCCESS
(o, si lo deseafalse
, que se convertiría implícitamente a cero) para indicar la terminación normal. Para indicar una falla, puede regresarEXIT_FAILURE
. Cualquier otro significado del código está definido por la implementación (en sistemas POSIX significaría un código de error real).El programa finalizará cuando el flujo de ejecución llegue al final de la función principal.
Para terminarlo antes, puede usar la función de salida (int status), donde status es un valor devuelto a lo que inició el programa. 0 normalmente indica un estado sin error
fuente
O devuelve un valor de usted
main
o usa laexit
función. Ambos toman una int. Realmente no importa qué valor devuelva a menos que tenga un proceso externo que esté atento al valor de retorno.fuente
Si tiene un error en algún lugar profundo del código, arroje una excepción o configure el código de error. Siempre es mejor lanzar una excepción en lugar de establecer códigos de error.
fuente
Generalmente usaría el
exit()
método con un estado de salida apropiado .Cero significaría una carrera exitosa. Un estado distinto de cero indica que se ha producido algún tipo de problema. Este código de salida lo utilizan los procesos primarios (por ejemplo, los scripts de shell) para determinar si un proceso se ha ejecutado correctamente.
fuente
return 0;
. Supongo queexit()
es asíassert(false);
y, por lo tanto, debe usarse solo en el desarrollo para problemas de captura temprana.Más allá de llamar a exit (error_code), que llama a los controladores atexit, pero no a los destructores RAII, etc., cada vez uso más excepciones.
Más y más mi programa principal se ve así
donde secundario_principal donde se colocan todas las cosas que originalmente se colocaron, es decir, el principal original se renombra secundario_principal, y se agrega el código auxiliar principal anterior. Esto es solo un detalle, por lo que no hay demasiado código entre la bandeja y la captura en main.
Si lo desea, capture otros tipos de excepción.
Me gusta mucho detectar tipos de error de cadena, como std :: string o char *, e imprimirlos en el controlador catch en main.
El uso de excepciones como esta permite al menos llamar a los destructores RAII, para que puedan hacer la limpieza. Que puede ser agradable y útil.
En general, el manejo de errores C - salida y señales - y el manejo de errores C ++ - excepciones try / catch / throw - juegan juntos de manera inconsistente en el mejor de los casos.
Entonces, donde detectas un error
o algún tipo de excepción más específico.
fuente
exit
a su programa. Ya que estás dentromain
, puedes simplementereturn exitCode;
.Si su declaración if está en Loop, puede usar
Si desea escapar de algún código y continuar en bucle Use:
Seguir;
Si su declaración if no está en Loop, puede usar:
fuente
Amigo ... la
exit()
función se define en stdlib.hPor lo tanto, debe agregar un preprocesador.
Poner
include stdlib.h
en la sección del encabezadoLuego use
exit();
donde quiera pero recuerde poner un número entero en el paréntesis de salida.por ejemplo:
fuente
Si la condición que estoy probando es realmente una mala noticia, hago esto:
Esto me da un buen coredump desde donde puedo examinar la situación.
fuente
Para romper una condición, use el retorno (0);
Entonces, en su caso sería:
fuente