2010-06-03 9 views
12

Es ésto buenas prácticas de programación en C++:C++ probar experiencias de captura

try { 
// some code 

} 
catch(someException) { 
// do something 
} 
catch (...) 
{ 

// left empty <-- Good Practice??? 
} 
+2

Nunca uso ... aparte en 'main' como último recurso. Si quiero capturarlos a todos, uso una 'std :: exception', al menos puedes imprimirla y obtener una idea de la causa –

+1

Y capturar por referencia. – ereOn

Respuesta

41

No! ¡Esa es una práctica terrible!

Casi en el único momento en que debería catch (...) y no volver a lanzar la excepción sería en main() para detectar las excepciones no controladas y para mostrar o registrar un error antes de salir.

Si tiene catch (...), no tiene absolutamente ninguna idea de qué excepción se echó, y por lo tanto no puede saber si es seguro continuar funcionando.

+1

Y, como resultado, tendrá problemas para depurar el programa, ya que este bloque catch-all ocultará errores. – mcandre

+0

@mcandre: el depurador de Visual Studio proporciona la primera oportunidad de manejo de excepciones que se rompe cuando se lanza una excepción; Estoy seguro de que otros depuradores proporcionan este tipo de capacidad también. El truco 'catch (...)' in 'main()' puede permitir una salida "normal" sin depender de 'std :: unexpected()' y 'std :: terminate()'. –

+0

Y nunca he encontrado que las excepciones de depuración fueran tan fáciles, ya que la pila se arruinó cuando la obtuviste. Por lo tanto, normalmente hago afirmaciones en lugares donde se lanzan excepciones. –

7

Bueno, depende de su aplicación y del problema que está tratando de resolver. Pero, en general, no es una buena idea tragarse excepciones desconocidas. Por lo menos, registraría algo.

Editar: como señaló Noah Roberts, la única y única vez que esto podría ser una idea razonable sería en un destructor. Es importante suprimir excepciones en destructores, de lo contrario, podría tener múltiples excepciones activas. Esto podría suceder, por ejemplo, si se produce una excepción y, como resultado de la eliminación de la pila, se llama a algún destructor. Si ese destructor arroja una excepción, tendrá 2 excepciones activas. C++ llamará a std :: terminate(), que de forma predeterminada finalizará su programa. Puede instalar un controlador para esta condición, pero probablemente no hay mucho que pueda hacer aparte de registrar lo que está sucediendo.

Aún así, incluso en un destructor, probablemente deba registrar algo dentro del catch (...). Sin embargo, dependiendo de qué destructor sea, es posible que no tenga su recurso de registro disponible. Pero en la mayoría de los casos aún puede usar std::cerr.

+0

No creo que sea aceptable usar 'catch (...)' en un destructor. Si no sabe exactamente qué excepciones puede arrojar una operación y bajo qué circunstancias, no debe hacer esa operación en un destructor. –

+0

A menudo no tiene otra opción. Si está implementando RAII, debe deshacer lo que hizo en el constructor. Es posible que no esté claro qué excepciones se lanzan bajo todas las circunstancias en el código de un tercero. Por lo tanto, a menudo es más seguro simplemente 'catch (...)' para cubrir todos los casos. Por supuesto, debe iniciar sesión si puede. –

2

Esta es una de esas preguntas "depende". Si está tratando con una biblioteca de terceros mal documentada que siguió adelante y definió su propia excepción que no hereda de std :: exception, es posible que no tenga otra opción. Por otra parte, solo dejaría eso en la parte de depuración de mi código.

7

No. Esto no es una buena práctica de programación en C++ o en cualquier otro idioma.

Las fallas silenciosas son malas y te morderán tarde o temprano.

Si va a catch (...) al menos lo mínimo que debe hacer es que lo está haciendo. Es posible que también necesite delete algunos objetos si no está utilizando RAII.

9

buena práctica es simplemente:

try { 
// some code 

} 
catch(const someException & e) { 
// do something 
} 

Porque sabes lo excepción (s) que se desea capturar.

catch (...) debería estar solo en su main() y en el punto de entrada de los hilos (ninguna excepción debería dejar hilos), después de un catch (const std :: exception & e).

+1

+1 para agregar 'const &'. – Johnsyweb

4

La única vez que puedo pensar en dónde podría ser necesario, aunque eso todavía no significa que sea bueno, está en un destructor. Los destructores no pueden lanzar o vas a tener problemas mucho peores que cualquiera que haya sido la excepción (salvo un bad_alloc). Si no hay nada que puedas hacer al respecto cuando algo se tira, tu captura estará vacía. No puedes volver a lanzar porque estás en un destructor ...es realmente todo lo que puedes hacer en esa situación.

Sin embargo, una afirmación allí o algo estaría justificado.

Por supuesto, otros han mencionado los hilos. Simplemente no hago MT, así que no sé los problemas allí.

4

Comer excepciones es una mala idea.

Como mínimo, implemente algún tipo de registro para sus excepciones. Es posible que desee considerar volver a lanzar la excepción con un mensaje de error que describa mejor el problema.

2

Como práctica estándar, esta es una muy mala idea. Si comienzas a tragar excepciones cuando no sabes qué hacer con ellos, entonces eres un. evitando que sean tratados en lugares más adecuados en la pila de llamadas, y b. dando una oportunidad para que su programa continúe en un estado erróneo.

Sin embargo, dicho esto, existe la posibilidad de que usted como programador haya tomado la determinación correcta y lógica de que es un momento apropiado para tragar una excepción. Esto podría requerir pasos de seguimiento, como realizar una limpieza e informar al usuario que una operación que iniciaron falló.

En pocas palabras, si no puede determinar las consecuencias de la captura, no atrape.

0

En realidad, realmente depende de lo que su programa intente hacer, sin embargo, la mayoría de las veces no es una buena idea tragarse las excepciones y continuar ejecutándose como si nada pasara, necesita ser informado de los problemas que realmente tenía el código. donde se estrelló etc ...

Başak Bilgi

0

Nunca hablar en absolutos. Diría que casi nunca deberías tragar una excepción. Sin embargo, aquí es un lugar en mi código donde he hecho sin realmente me molesta:

class _ACLASS dstream 
    : public ofstream 
{ 
//... 
    long GetSize (void); 
//... 
Protected: 
    string CheckRotation(void); 
//... 
}; 

string dstream::CheckRotation(void) 
{ 
//... 
     // rotate if they aren't the same (it's a new day) 
     // or our current file size exceeds the limit. 
     if (currDay != newDay || GetSize() > fileSizeLimit * ONE_MEGABYTE) 
     { 
//...    
      Purge(); // while all files are closed, look for purge opportunity 
      clear(); 
      open(Destination); 
//... 
} 

// Return current file size 
long dstream::GetSize (void) 
{ 
    long retval =0; 
    try { // PBI 1227 was caused by this not being trapped. 
     retval = (long)tellp(); 
    } catch (...) { 
     retval =0; 
    } // Swallow the exception if any 

    return retval; 
} 

Aquí sólo estoy tratando de determinar si mi archivo de registro ha superado 1 M bytes (o Hwever muchas M bytes permitido por fileSizeLimit), y si es así, gire el registro. Si recibo una excepción aquí, solo reportaré un tamaño de 0 bytes a la persona que llama y la persona que llama no elegirá rotar el registro en este momento. En la próxima llamada, es probable que obtenga una respuesta correcta y la pase.

Supongo que si tellp() arroja una excepción en cada llamada, mi log no rotará hasta la medianoche. Pero dudo que esto pueda suceder (y nunca lo he visto en el campo)

+3

Usted ** no ** simplemente 'traga' esa excepción; estás * haciendo algo * cuando ocurre una excepción ... estableciendo 'retval' en' 0'. –