Pergunta

Em C++, estou tentando capturar todos os tipos de exceções em uma única captura (como catch(Exception) em C#).Como isso é feito?E mais, como capturar exceções de divisão por zero?

Foi útil?

Solução

catch (...)
{
   // Handle exceptions not covered.
}

Considerações importantes:

  • Uma abordagem melhor é capturar tipos específicos de exceções das quais você pode realmente se recuperar, em oposição a todas as exceções possíveis.
  • catch(...) também capturará certas exceções sérias no nível do sistema (varia dependendo do compilador) das quais você não será capaz de recuperar de forma confiável.Capturá-los dessa maneira e depois engoli-los e continuar pode causar mais problemas sérios em seu programa.
  • Dependendo do seu contexto, pode ser aceitável usar catch(...), desde que a exceção seja lançada novamente.Nesse caso, você registra todas as informações úteis do estado local e, em seguida, lança novamente a exceção para permitir que ela se propague.No entanto, você deve ler sobre o Padrão RAII se você escolher esta rota.

Outras dicas

Você não quero usar catch (...) (ou seja,pegue com as reticências), a menos que você realmente, definitivamente, provavelmente tenha necessidade disso.

A razão para isso é que alguns compiladores (Visual C++ 6, para citar os mais comuns) também transformam erros como falhas de segmentação e outras condições realmente ruins em exceções que você pode manipular com prazer usando catch (...).Isso é muito ruim, porque você não vê mais os travamentos.

E tecnicamente, sim, você também pode capturar a divisão por zero (você terá que usar o "StackOverflow" para isso), mas você realmente deveria evitar fazer tais divisões em primeiro lugar.

Em vez disso, faça o seguinte:

  • Se você realmente sabe que tipo de exceção esperar, capture esses tipos e nada mais, e
  • Se você mesmo precisar lançar exceções e capturar todas as exceções que lançará, faça com que essas exceções derivem de std::exception (como sugeriu Adam Pierce) e capture-as.

Se você estiver no Windows e precisar lidar com erros como divisão por zero e violação de acesso, poderá usar um tradutor de exceção estruturado.E então dentro do seu tradutor você pode lançar uma exceção c++:

void myTranslator(unsigned code, EXCEPTION_POINTERS*)
{
    throw std::exception(<appropriate string here>);
}

_set_se_translator(myTranslator);

Observe que o código informará qual foi o erro.Além disso, você precisa compilar com a opção /EHa (C/C++ -> Code Generatrion -> Enable C/C++ Exceptions = Yes with SEH Exceptions).

Se isso não fizer sentido, verifique a documentação de [_set_se_translator](http://msdn.microsoft.com/en-us/library/5z4bw5h5(VS.80).aspx)

Se capturar todas as exceções - incluindo as do sistema operacional - é realmente o que você precisa, dê uma olhada no seu compilador e no sistema operacional.Por exemplo, no Windows você provavelmente tem a palavra-chave "__try" ou a opção do compilador para fazer "try/catch" capturar exceções SEH, ou ambos.

Faça com que todas as suas classes de exceção personalizadas herdem de std::exception, então você pode simplesmente capturar std::exception.Aqui está um exemplo de código:

class WidgetError
    : public std::exception
{
public:
    WidgetError()
    { }

    virtual ~WidgetError() throw()
    { }

    virtual const char *what() const throw()
    {
        return "You got you a widget error!";
    }
};

Em C++, o padrão não define uma exceção de divisão por zero e as implementações tendem a não lançá-las.

Você pode, é claro, usar catch (...) { /* code here */ }, mas realmente depende do que você deseja fazer.Em C++ você tem destruidores determinísticos (nenhuma dessas besteiras de finalização), então se você quiser limpar, o correto a fazer é usar RAII.

Por exemplo.em vez de:

void myfunc()
{
    void* h = get_handle_that_must_be_released();
    try { random_func(h); }
    catch (...) { release_object(h); throw; }
    release_object(h);

}

Faça algo como:

#include<boost/shared_ptr.hpp>

void my_func()
{
    boost::shared_ptr<void> h(get_handle_that_must_be_released(), release_object);
    random_func(h.get());
}

Crie sua própria classe com um destruidor se você não usar o boost.

Se bem me lembro (já faz um tempo que não vejo C++), acho que o seguinte deve resolver

try
{
 // some code
}
catch(...)
{
 // catch anything
}

e um rápido google (http://www.oreillynet.com/pub/a/network/2003/05/05/cpluspocketref.html) parece provar que estou correto.

Licenciado em: CC-BY-SA com atribuição
Não afiliado a StackOverflow
scroll top