2010-11-08 12 views
5

¿Cuáles podrían ser las implicaciones de tener una función miembro setter en una clase de excepción? La motivación para tener un colocador es que a veces no hay suficientes datos disponibles en el punto de lanzamiento para manejar la excepción adecuadamente en el punto de captura; por lo que la información adicional debe agregarse cuando se desenrolla la pila.Setter en la clase de excepción

+1

Suena como una idea razonable. – Jay

+1

y qué código se ejecutará * mientras * la pila se está desenrollando? – Anon

+0

Quiere decir en otro bloque catch. – Skurmedel

Respuesta

3

Si bien puedes diagnosticar la excepción original, preferiría la técnica utilizada en Java: captas el original y lanzas una nueva excepción que hace referencia al original como causa.

+0

@Anon: y acabas de perder el marco de la pila ... –

+0

@Matthieu: De acuerdo. Si lanza una nueva excepción, perderá la información de depuración de la pila. – Puppy

+0

Incrustar el original podría exponerlo al problema de corte, si captura una clase base, pero la excepción detectada es algo derivado. Tendría que tirar y atrapar con el puntero, pero eso no es típico y crea algunos problemas propios. –

1

Antes que nada, parece una buena idea.

Uso SEH (manejo de excepciones específico de Windows, no relacionado con C++) en lugar de manejo de excepciones C++. Específicamente debido a esto, permite recopilar mucha más información antes de que comience el desenrollamiento de la pila.

Pero nunca he pensado en lanzar un tipo que "recopile" información.

Técnicamente hablando, no hay ningún problema. Sé cómo MSVC implementa el manejo de excepciones (hasta el nivel de ensamblador), y la idea no tiene nada de malo. Hay algunos puntos que deben mencionarse:

  1. catch El bloque se invoca después la pila se haya desenrollado. De modo que todo lo que está dentro del bloque try apropiado tiene ya destruido.
  2. Al volver a tirar una excepción, se produce un gran golpe de rendimiento.
1

Supongo que el problema subyacente es que el código throwing (bajo nivel) no tiene tanto contexto/información como el código más arriba tendría.

Puede crear una nueva excepción que describa mejor la excepción, envolviendo la excepción original como una excepción interna. He hecho esto algunas veces, pero me doy cuenta de que esto no es práctico en todas las circunstancias.

Sé que algunos marcos tienen una propiedad de "Datos" que es más o menos un diccionario con datos arbitrarios. No me parece mal, aunque se abre para el abuso. Probablemente no debería usarse para tomar decisiones programáticas, debería ser para consumo humano.

Si algo capta la excepción y toma decisiones basadas en el parámetro X, podría volverse bastante complicado.

5

Mira la biblioteca Boost.Exception y más precisamente this page en el párrafo titulado Adición de datos arbitrarios a excepción Activo:

void parse_file(char const * file_name) 
{ 
    boost::shared_ptr<FILE> f = file_open(file_name,"rb"); 
    assert(f); 
    try 
    { 
     char buf[1024]; 
     file_read(f.get(), buf, sizeof(buf)); 
    } 
    catch(boost::exception & e) 
    { 
     e << boost::errinfo_file_name(file_name); 
     throw; 
    } 
} 

Personalmente, creemos que la técnica muy eficaz. Modifique la excepción (agregando contexto) y vuelva a lanzar.

Contrariamente a Java, en C++ usted decide si incluye o no el marco de pila al construir su excepción, por lo que no corre el riesgo de perderlo y todavía se referirá al punto del código que arrojó la primera excepción, aunque tiene un contexto significativo.

+1

Encontrarlo en Boost parece ser un buen respaldo de la técnica, incluso si no te gusta usar Boost. –

Cuestiones relacionadas