una terminar tecla salir salida programa proceso lenguaje funcion ejemplos ejecucion detener con como codigo cerrar c++

c++ - terminar - salida de un programa en c



Cómo finalizar el código C++ (14)

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.

int main() { ofstream os("out.txt"); os << "Hello, Can you see me!/n"; return(0); //exit(0); }

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.

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 declaración if es verdadera, finalice el código de esta manera:

if (x==1) { kill code; }


Devuelva un valor de su main o use la función de exit . Ambos toman una int. Realmente no importa qué valor devuelva a menos que tenga un proceso externo que esté atento al valor de retorno.


El programa terminará cuando el flujo de ejecución llegue al final de la función principal.

Para finalizarlo antes de eso, 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


El tipo ... la función exit() se define en stdlib.h

Por lo tanto, debe agregar un preprocesador.

Ponga include stdlib.h en la sección de encabezado

Luego use exit(); donde quieras pero recuerda poner un número entero en el paréntesis de salida.

por ejemplo:

exit(0);


Generalmente usaría el método exit() 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 (p. Ej., Scripts de shell) para determinar si un proceso se ha ejecutado correctamente.


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 ++ hace uso de 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 clase std::ofstream [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 se 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

#include <fstream> #include <exception> #include <memory> void inner_mad() { throw std::exception(); } void mad() { std::unique_ptr<int> ptr(new int); inner_mad(); } int main() { std::ofstream os("file.txt"); os << "Content!!!"; int possibility = /* either 1, 2, 3 or 4 */; if(possibility == 1) return 0; else if(possibility == 2) throw std::exception(); else if(possibility == 3) mad(); else if(possibility == 4) exit(0); }

Lo que sucede en cada posibilidad es:

  • Posibilidad 1: El retorno esencialmente deja el alcance de la función actual, por lo que conoce el final del ciclo de vida del sistema operativo, por lo que llama a su destructor y realiza una limpieza adecuada al cerrar y vaciar el archivo en el disco.
  • Posibilidad 2: Lanzar una excepción también se ocupa del ciclo de vida de los objetos en el alcance actual, haciendo así una limpieza adecuada ...
  • Posibilidad 3: ¡ Aquí el desbobinado de la pila entra en acción! Aunque se lanza la excepción en inner_mad , el desbobinador pasará por la pila de mad y main para realizar una limpieza adecuada, todos los objetos se destruirán correctamente, incluidos ptr y os .
  • Posibilidad 4: Bueno, ¿aquí? std::exit es una función de C y no es consciente ni compatible con los modismos de C ++. No realiza limpieza en sus objetos, incluido el sistema os 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!
  • Otras posibilidades: Simplemente dejará el alcance principal, al realizar un return 0 implícito 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 acabo de decirle (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 main!

Debe hacer esto siempre que sea posible; siempre prefiere 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 y EXIT_SUCCESS 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 función noexcept en el medio de la pila de llamadas. Esto se establece en §15.5.1 [excepto.terminal] :

  1. En algunas situaciones, se debe abandonar el manejo de excepciones para técnicas de manejo de errores menos sutiles. [Nota: Estas situaciones son:

    [...]

    - cuando el mecanismo de manejo de excepciones no puede encontrar un controlador para una excepción lanzada (15.3), o cuando la búsqueda de un controlador (15.3) encuentra el bloque más externo de una función con una noexcept que no permite la excepción (15.4), o [...]

    [...]

  2. En tales casos, std :: terminate () se llama (18.8.3). En la situación en la que no se encuentra un controlador coincidente, se define la implementación si la pila se desenrolla o no antes de llamar a std :: terminate () [...]

¡Entonces tenemos que atraparlo!

¡Lanza una excepción y atrápalo en main!

Dado que las excepciones no detectadas pueden no desenrollar 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 o EXIT_SUCCESS ).

Entonces, una configuración posiblemente buena sería:

int main() { /* ... */ try { // Insert code that will return by throwing a exception. } catch(const std::exception&) // Consider using a custom exception type for intentional { // throws. A good idea might be a `return_exception`. return EXIT_FAILURE; } /* ... */ }

[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] :

Terminar el programa sin abandonar el bloque actual (por ejemplo, llamando a la función std :: exit (int) (18.5)) no destruye ningún objeto con una duración de almacenamiento automática (12.4) . Si se llama a std :: exit para finalizar un programa durante la destrucción de un objeto con una duración de almacenamiento estático o de subprocesos, el programa tiene un comportamiento indefinido.

Piénsalo ahora, ¿por qué harías tal cosa? ¿Cuántos objetos has dañado dolorosamente?

Otras alternativas [como malas]

Hay otras formas de terminar 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 terminación normal del programa y llama a los controladores std::at_quick_exit , no se realiza ninguna otra limpieza.
  • std::exit provoca una terminación normal del programa y luego llama a los controladores std::atexit . 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 al std::terminate_handler que llama a std::abort por defecto.

La gente dice "salida de llamada (código de retorno)", pero esta es una mala forma. En programas pequeños está bien, pero hay varios problemas con esto:

  1. Terminarás teniendo múltiples puntos de salida del programa
  2. Hace que el código sea más complicado (como usar goto)
  3. No puede liberar memoria asignada en tiempo de ejecución

Realmente, la única vez que debe salir del problema es con esta línea en main.cpp:

return 0;

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.



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í

int main(int argc, char** argv) { try { exit( secondary_main(argc, argv ); } catch(...) { // optionally, print something like "unexpected or unknown exception caught by main" exit(1); } }

donde secundaria_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 al menos permite que se invoquen los destructores RAII, para que puedan realizar 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

throw "error message"

o algún tipo de excepción más específico.


Para romper una condición, use el retorno (0);

Entonces, en su caso sería:

if(x==1) { return 0; }


Si la condición que estoy probando es realmente una mala noticia, hago esto:

*(int*) NULL= 0;

Esto me da un buen coredump desde donde puedo examinar la situación.


Si su declaración if está en Loop, puede usar

break;

Si desea escapar de algún código y continuar en bucle Use:

continuar;

Si su declaración if no está en Loop, puede usar:

return 0; Or exit();


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.


return 0; ponlo donde quieras dentro de int main() y el programa se cerrará inmediatamente.