5

Así que estaba escribiendo un código y noté que aparte de sintáctico, tipo y otros errores en tiempo de compilación, C++ no arroja ninguna otra excepción. Así que decidí probar esto con un programa muy trivial:C++ Exception Handling

#include<iostream> 

int main() { 
    std::count<<5/0<<std::endl; 
return 1 
} 

Cuando compilado usando g ++, g ++ me dio una advertencia diciendo que estaba dividiendo por 0. Pero todavía el código compilado. Luego, cuando lo ejecuté, imprimió un número arbitrario realmente grande. Cuando quiero saber es, ¿cómo lidia C++ con las excepciones? La división de enteros por 0 debería ser un ejemplo muy trivial de cuándo debe lanzarse una excepción y el programa debe terminar.

¿Tengo que encerrar esencialmente todo mi programa en un gran bloque de prueba y luego detectar ciertas excepciones? Sé en Python cuando se lanza una excepción, el programa terminará inmediatamente e imprimirá el error. ¿Qué hace C++? ¿Hay incluso excepciones de tiempo de ejecución que detienen la ejecución y matan el programa?

Respuesta

8

Existen excepciones de tiempo de ejecución, pero no todo lo que está "mal" da como resultado una excepción en tiempo de ejecución. Por ejemplo, acceder a una matriz fuera de límites o desreferenciar un puntero nulo es simplemente un "comportamiento indefinido", lo que significa que puede suceder cualquier cosa. La división por cero también cae en la categoría "indefinido".

La razón de algunas operaciones que da como resultado un "comportamiento indefinido" en lugar de una excepción es la eficiencia. Supongamos que un acceso de matriz fuera de límites requiere una excepción para ser lanzado. Entonces, el compilador debería generar código para cada acceso a la matriz para verificar si está fuera de límites, y si es así, lanzar una excepción. Eso es un montón de control, la mayoría de los cuales es innecesario. En cambio, lo que hacen los compiladores es generar las instrucciones para el acceso al elemento suponiendo que está dentro de los límites. Si sucede que está fuera de límites, sucede lo que ocurra (por ejemplo, falla de segmentación). Si quiere realizar una comprobación, siempre puede codificarla explícitamente.

Esto hace que C++ sea más poderoso que los lenguajes que siempre hacen comprobaciones (por ejemplo, Java o python) porque puede elegir cuándo quiere que se haga una comprobación y cuándo no. (Por otro lado, hace que C++ sea menos seguro que Java o Python. Es una desventaja).


En cuanto a lo que ocurre cuando se produce una excepción, pero no se detecta en cualquier lugar, por lo general implementaciones compilador mostrará un mensaje de error que contiene de what() la excepción. En su ejemplo, eso no es aplicable porque no se lanza ninguna excepción de tiempo de ejecución.

+0

Gracias eso tiene sentido. Entonces otra pregunta. Si en lugar de usar std :: cout, utilizo std :: cerr, ¿arrojaría esto una excepción, o simplemente imprimiría en la secuencia de error? Y si creo mi propia excepción (digamos foo) y en mi código digo throw foo, ¿se matará mi programa inmediatamente y se imprimirá foo.what()? ¿O tengo que decirle explícitamente a C++ que lo haga? – user1413793

+0

@ user1413793: Si escribe en 'std :: cerr', simplemente se imprimirá en la secuencia de error. Puede enviar el flujo de salida y el flujo de error a diferentes lugares a través de la redirección en la línea de comando ('>' vs '2>'). Si "arrojas" una excepción, y no la encuentras en ningún lado, el programa terminará inmediatamente e imprimirá un mensaje de error. (Más precisamente, se llamará a una función llamada 'std :: terminate', cuyo comportamiento predeterminado es terminar el programa e imprimir el mensaje de la excepción. Puede anular el comportamiento llamando a' std :: set_terminate'. Mire eso si usted Estoy interesado. – HighCommander4

0

Visual C++ señala esto correctamente como un error de división por cero. Entonces, si no se compila, no se trata de ejecutarlo.

+0

pero ¿es "correcta" de acuerdo con la norma? Sólo curioso. –

+0

La división por cero no está definida incluso antes de cualquier estándar, ¿verdad? – Superman

3

Sí, hay excepciones de tiempo de ejecución. Un ejemplo es out_of_range, que se lanza por vector::at.

Sin embargo, la división por cero no está definida (C++ 0x §5.6/4):

Si el segundo operando de/o% es cero el comportamiento se nida inde fi.

Puede fallar en la compilación, lanzar una excepción inventada, imprimir "algún número arbitrario realmente grande" o segfault.

+0

¡Bien, gracias! Estaba confundido porque otros lenguajes arrojan una excepción, pero eso tiene sentido :) – user1413793

2

C++ solo arroja excepciones estándar que están bien definidas en el estándar de C++.(Sí Incluye algunas excepciones en tiempo de ejecución)

un entero dividido por cero no es una excepción ++ estándar de C (Técnicamente se trata de un comportamiento indefinido ). Por lo tanto, no se lanzará ninguna excepción implícita. Un compilador particular puede asignar el error en tiempo de ejecución a algún tipo de excepción (deberá verificar la documentación del compilador para esto, algunos compiladores dividen el mapa por cero en alguna excepción), de ser así, puede detectar esa excepción en particular. Sin embargo, tenga en cuenta que esto no es un comportamiento portátil y no funcionará para todos los compiladores.

Lo mejor que puede hacer es verificar la condición de error (divisor igual a cero) usted mismo y lanzar una excepción explícitamente en tales casos.

EDIT: Para responder a la comentario

class A 
{ 
    public: 
     void f() 
     { 
      int x; 
      //For illustration only 
      int a = 0; 
      if(a == 0) 
        throw std::runtime_error("Divide by zero Exception"); 
      x=1/a; 
     } 

     A() 
     { 
       try 
       { 
        f(); 
       } 
       catch(const std::runtime_error& e) 
       { 
        cout << "Exception caught\n"; 
        cout << e.what(); 
       } 
     } 
};  
+0

Lanzaría una excepción, porque el programa terminará y se imprimirá la excepción, o ¿tendré que atrapar entonces la excepción y explícitamente decirle a C++ qué hacer? – user1413793

+1

@ user1413793: actualizó la respuesta. Tendrá que atrapar la excepción y decidir qué hacer al respecto. –