2009-06-24 9 views
36

C++ proporciona una sintaxis para excepciones controladas, por ejemplo:¿Por qué no se verifican las excepciones en C++ por el compilador?

void G() throw(Exception); 
void f() throw(); 

Sin embargo, el Visual C++ compilador no comprueba ellos; la bandera de tiro simplemente se ignora. En mi opinión, esto hace que la característica de excepción no se pueda usar. Entonces mi pregunta es: ¿hay alguna manera de que el compilador compruebe si las excepciones se capturan/vuelven a lanzar correctamente? Por ejemplo, un complemento de Visual C++ o un compilador de C++ diferente.

PS. Quiero que el compilador compruebe si las excepciones están correctamente capturadas, de lo contrario terminarás en una situación en la que tienes que poner un truco a cada llamada de función que hagas, , incluso si explícitamente afirman que no lanzarán nada.

Actualización: el compilador de Visual C++ muestra una advertencia al lanzar una función marcada con throw(). Esto es genial, pero lamentablemente, la advertencia no aparece cuando llamas a una subrutina que podría arrojar. Por ejemplo:

void f() throw(int) { throw int(13); } 
void h() throw() { g(); } //no warning here! 
+0

Nunca escuché acerca de las excepciones comprobadas en C++, pero ahora sé sobre la especificación de excepciones y que a Visual C++ no le interesan mucho, eche un vistazo aquí: http://msdn.microsoft.com/ es-us/library/wfa0edys.aspx – Skurmedel

+1

Visual C++ no lo ignora del todo ... agregar throw() al final de una función le dice a Visual C++ que puede asumir que la función no arroja, por ejemplo con fines de optimización, y si la función realmente arroja, entonces cualquier cosa puede suceder. El estándar dice que si una función está marcada, throw() sale debido a una excepción, luego std :: unexpected(), que generalmente arroja std :: bad_exception.Esto es muy diferente de "cualquier cosa puede suceder". – Doug

+0

Si las especificaciones de excepción son pistas para los compiladores y no son requisitos para hacer algo, serían potencialmente útiles. El comportamiento estándar es, en mi opinión, inútil. –

Respuesta

29

Las especificaciones de excepción son bastante inútiles en C++.

No es forzada que no hay otras excepciones serán lanzados, sino simplemente que la función global unexpected() será llamado (que puede ser ajustado)

El uso de especificaciones de excepción se reduce principalmente a engañarse a sí mismo (o sus compañeros) en un falso sentido de seguridad. Mejor simplemente no molestarse.

+0

"Imposible" es un reclamo bastante fuerte. ¿Por qué la imposición de especificaciones de excepción es imposible con plantillas? –

+0

pensando en ello, tienes razón, por supuesto, no sé de dónde saqué eso, eliminé el párrafo – Pieter

+1

Sentimiento correcto pero argumento completamente equivocado. C++ (a diferencia de Java y la mayoría de los otros lenguajes modernos) comprueba la especificación de excepciones en tiempo de ejecución, no en tiempo de compilación. Desafortunadamente, este experimento en especificaciones de excepción no ha funcionado (aparte de no tirar). –

14

Tener un vistazo a esto:

http://www.gotw.ca/publications/mill22.htm

básicamente especificaciones de excepción son impracticables/inservible, pero eso no hace excepciones inviable.

En cuanto a su pregunta, no hay forma de que el compilador compruebe que cada tipo arrojado está atrapado en algún lugar más alto en el código, supongo que las unidades de compilación lo dificultan y es imposible hacerlo para el código destinado a ser utilizado en una biblioteca (donde el nivel superior no está disponible en el momento de la compilación). Si quieres estar seguro de que todo está atrapado, pega una trampa (...) en la parte superior de tu código.

+1

Gracias por su respuesta. El problema con la captura (...) en el nivel superior es que en C++ casi no se obtiene información sobre lo que sucedió: no hay información de tipo y no hay pila de llamadas. Este problema puede solucionarse arrojando un único tipo de excepciones de una manera muy disciplinada, pero esto se siente propenso a errores. –

+1

@ Dimitri: Estoy en desacuerdo, siempre arrojo excepciones derivadas de std :: exception, no hay necesidad de una gran cantidad de disciplina para hacer esto ... – Patrick

0

No puedo verificar esto por falta de una instalación de MSVC, pero ¿está seguro de que el compilador ignora la especificación throw()?

This MSDN page sugiere que Microsoft conoce throw() y espera que su compilador lo maneje correctamente. Bueno, casi, vea la nota sobre cómo se apartan del estándar ANSI/ISO en algunos detalles.

Edit: En la práctica, sin embargo, estoy de acuerdo con Patrick: Las especificaciones de excepción son en su mayoría inútiles.

8

Porque el estándar lo dice. La declaración de excepción no significa que no se lanzará ninguna otra excepción. Significa que si se lanza una excepción no declarada, se llamará una función global especial llamada inesperada(), que por defecto finaliza el programa. Generalmente se desaconseja declarar excepciones en las funciones (tal vez excepto en la lista de excepciones vacías) ya que el comportamiento estándar no es muy útil.

9

Para detectar antes del tiempo de ejecución casos como ...

extern void f() throw (class Mystery); 
void g() throw() { 
    f() ; 
} 

... necesita análisis estático. Sí, el compilador está haciendo un montón de análisis estático, pero porque el estándar es "raise std :: unexpected si el lanzamiento no coincide", y es perfectamente legal escribir una rutina que arroje un objeto que no coincida con el especificador. , los implementadores del compilador ni advierten ni comentan.

herramientas de análisis estático que pretenden ofrecer un servicio de alerta se encuentran de lint for C++ ...

1560 Gimpel Software Excepción no detectada 'Nombre' no con el tiro-lista para la función 'Símbolo'

y, de acuerdo con this answer a una pregunta anterior, QA C++.

37

Lo curioso es que Java ha comprobado excepciones, y los programadores de Java también las odian.

especificaciones excepción en C++ son inútiles por 3 razones:

1. C especificaciones de excepción ++ inhiben optimización.

Con la excepción, posiblemente, de throw(), los compiladores insertan código adicional para comprobar que cuando se lanza una excepción, coincide con la especificación de excepción de funciones durante un desenrollado de la pila. Manera de hacer que tu programa sea más lento.

2. C++ especificaciones de excepción no se compilador reforzadas

En lo que se refiere a su compilador, el siguiente es sintácticamente correcta:

void AStupidFunction() throw() 
{ 
    throw 42; 
} 

Lo que es peor, nada útil sucede si usted viola una especificación de excepción. ¡Tu programa simplemente termina!

3. Las especificaciones de excepción de C++ son parte de la firma de una función.

Si tiene una clase base con una función virtual e intenta sobrescribirla, las especificaciones de excepción deben coincidir exactamente. Por lo tanto, será mejor que planees con anticipación, y sigue siendo un dolor.

struct A 
{ 
    virtual int value() const throw() {return 10;} 
} 

struct B : public A 
{ 
    virtual int value() const {return functionThatCanThrow();} // ERROR! 
} 

Las especificaciones de excepción le dan estos problemas, y la ganancia para usarlos es mínima. Por el contrario, si evita por completo las especificaciones de excepción, la codificación es más fácil y evita estas cosas.

+0

¡Buena respuesta! Gracias. –

+0

¿podemos solucionar "throw 42;" ¿problema? – Anuj

Cuestiones relacionadas