2010-03-19 17 views
7

Hay algunos artículos finales "Nunca lanzar una excepción desde un destructor", y "std :: uncaught_exception() no es útil", por ejemplo:derecho de uso de std :: uncaught_exception en un destructor

Pero parece que no entiendo el punto. Así que escribí un pequeño ejemplo de prueba (ver abajo).

ya que todo está bien con el ejemplo de pruebas Me gustaría muy apreciar algunos comentarios con respecto a lo que podría estar mal con él?

resultados de las pruebas:

./main

 
    Foo::~Foo(): caught exception - but have pending exception - ignoring 
    int main(int, char**): caught exception: from int Foo::bar(int) 

./main 1

 
    Foo::~Foo(): caught exception - but *no* exception is pending - rethrowing 
    int main(int, char**): caught exception: from Foo::~Foo() 

ejemplo:

// file main.cpp 
// build with e.g. "make main" 
// tested successfully on Ubuntu-Karmic with g++ v4.4.1 
#include <iostream> 

class Foo { 
    public: 

    int bar(int i) { 
    if (0 == i) 
     throw(std::string("from ") + __PRETTY_FUNCTION__); 
    else 
     return i+1; 
    } 

    ~Foo() { 
    bool exc_pending=std::uncaught_exception(); 
    try { 
     bar(0); 
    } catch (const std::string &e) { 
     // ensure that no new exception has been created in the meantime 
     if (std::uncaught_exception()) exc_pending = true; 

     if (exc_pending) { 
     std::cerr << __PRETTY_FUNCTION__ 
        << ": caught exception - but have pending exception - ignoring" 
        << std::endl; 
     } else { 
     std::cerr << __PRETTY_FUNCTION__ 
        << ": caught exception - but *no* exception is pending - rethrowing" 
        << std::endl; 
     throw(std::string("from ") + __PRETTY_FUNCTION__); 
     } 
    } 
    } 

}; 

int main(int argc, char** argv) { 
    try { 
    Foo f; 
    // will throw an exception in Foo::bar() if no arguments given. Otherwise 
    // an exception from Foo::~Foo() is thrown. 
    f.bar(argc-1); 
    } catch (const std::string &e) { 
    std::cerr << __PRETTY_FUNCTION__ << ": caught exception: " << e << std::endl; 
    } 
    return 0; 
} 

AÑADIDO : En otras palabras: a pesar de las advertencias en algunos artículos, funciona como se esperaba, entonces, ¿qué podría estar mal con eso?

+2

¿Cuál es tu pregunta? Parece que estás observando el comportamiento esperado de un mecanismo que no debes usar. ¿Estás considerando usarlo fuera de un contexto de prueba/experimentación, y por qué? – Potatoswatter

+0

@Potatoswatter: la pregunta es: 'a pesar de las advertencias de algunos artículos que funciona como se espera - ¿y qué podría estar mal con él' –

+0

nuff Feria, pero eso no es citar lo que ha dicho, y es imposible saber lo que se espera,? apropiado o seguro en su contexto sin más información. La ruta segura, como Herb Sutter y muchos otros te dirán, es no tirar desde un destructor en primer lugar. – Potatoswatter

Respuesta

5

No hay nada técnicamente mal con su código. Es perfectamente seguro que nunca terminará accidentalmente porque lanzó una excepción cuando no era seguro hacerlo. El problema es que tampoco es útil, ya que ocasionalmente tampoco arrojará una excepción cuando sea seguro. La documentación de tu destructor básicamente tiene que decir "esto podría o no arrojar una excepción".

Si de vez en cuando no lanza una excepción, es posible que nunca arroje una excepción. De esa forma, al menos eres consistente.

6

Herb Sutter se refiere a un tema diferente. Está hablando de:

try 
{ 
} 
catch (...) 
{ 
    try 
    { 
     // here, std::uncaught_exception() will return true 
     // but it is still safe to throw an exception because 
     // we have opened a new try block 
    } 
    catch (...) 
    { 
    } 
} 

Así que el problema es que si std::uncaught_exception() vuelve verdadera no se sabe con certeza si se puede lanzar una excepción con seguridad o no. Usted termina teniendo que evitar lanzar una excepción cuando std::uncaught_exception() devuelve verdadero solo para estar seguro.

+0

@Samuel: '... refiriéndose a un problema diferente ...' Eso es lo que también pensé. Y, como no lanzo una excepción cuando uncaught_exception() devuelve verdadero, ¿cree que mi enfoque es seguro? –

+0

Eso no está bien. Su excepción es atrapada en ese punto. Deberías haber puesto el try/catch en un destructor, que se invoca al desenrollar la pila (debido a una excepción activa). En esa situación, una excepción * es * desenrollar activamente la pila, pero estás justo dentro de un bloque try/catch donde * puedes * lanzar una excepción. – dascandy

Cuestiones relacionadas