Existe um equivalente em c ++ do Java
try {
...
}
catch (Throwable t) {
...
}
Estou tentando depurar código Java / jni que chama funções nativas do Windows e a máquina virtual continua travando. O código nativo parece bem no teste de unidade e só parece travar quando chamado pelo jni. Um mecanismo genérico de captura de exceções seria extremamente útil.
Respostas:
captura todas as exceções do C ++, mas deve ser considerado um design incorreto. Você pode usar o novo mecanismo current_exception do c ++ 11, mas se você não tiver a capacidade de usar o c ++ 11 (sistemas de código legado que exigem uma reescrita), não precisará de um ponteiro de exceção nomeado para obter uma mensagem ou nome . Convém adicionar cláusulas de captura separadas para as várias exceções que você pode capturar e capturar apenas tudo na parte inferior para registrar uma exceção inesperada. Por exemplo:
fonte
Alguém deve adicionar que não é possível capturar "falhas" no código C ++. Aqueles não lançam exceções, mas fazem o que quiserem. Quando você vê um programa travando por causa de uma desreferência de ponteiro nulo, ele está fazendo um comportamento indefinido. Não existe
std::null_pointer_exception
. Tentar capturar exceções não ajudará lá.Apenas no caso de alguém estar lendo este tópico e achar que pode obter a causa das falhas do programa. Um depurador como o gdb deve ser usado.
fonte
try { .. } catch(...) { ... }
a captura usando sinal / sigaction, eu não chamaria de "captura" :) Se em um manipulador de sinal, é relativamente difícil para o programador saber onde no código ocorreu a falha (estou falando sobre detectar programaticamente isso), em comparação com try / catch.É assim que você pode fazer engenharia reversa do tipo de exceção a partir de dentro,
catch(...)
caso precise (pode ser útil ao capturar desconhecidos de uma biblioteca de terceiros) com o GCC:e se você puder usar o Boost, poderá tornar sua seção de captura ainda mais simples (externamente) e potencialmente multiplataforma
fonte
Observe que o
...
interior docatch
é uma elipse real, ie. três pontos.No entanto, como as exceções de C ++ não são necessariamente subclasses de uma
Exception
classe base , não há como realmente ver a variável de exceção lançada ao usar essa construção.fonte
catch
especificador do espaço reservado para o código existente em um comentário (// ...
) que obviamente não é a sintaxe do C ++.não é possível (em C ++) capturar todas as exceções de maneira portátil. Isso ocorre porque algumas exceções não são exceções em um contexto C ++. Isso inclui coisas como divisão por zero erros e outras. É possível invadir e, assim, obter a capacidade de gerar exceções quando esses erros ocorrerem, mas não é fácil e certamente não é fácil acertar de maneira portátil.
Se você deseja capturar todas as exceções de STL, pode fazer
O que permitirá que você use
e.what()
, que retornará aconst char*
, o que pode lhe informar mais sobre a exceção em si. Essa é a construção que mais se parece com a construção Java, sobre a qual você perguntou.Isso não ajudará se alguém for estúpido o suficiente para lançar uma exceção que não é herdada
std::exception
.fonte
Em suma, use
catch(...)
. No entanto, observe quecatch(...)
deve ser usado em conjunto comthrow;
basicamente:Esta é a maneira correta de usar
catch(...)
.fonte
Foo
o destruidor? Eu pensei que esse era o objetivo da RAII. No entanto, se você precisar de um ponteiro para, emFoo
vez de apenas criar oFoo
na pilha, será necessário agrupar o ponteiro em outra coisa declarada na pilha.é possível fazer isso escrevendo:
Mas há um risco muito imperceptível aqui: você não pode encontrar o tipo exato de erro que foi lançado no
try
bloco; portanto, use esse tipo decatch
quando tiver certeza de que, independentemente do tipo de exceção, o programa deve persistir da maneira definida nocatch
bloco.fonte
Você pode usar
mas isso é muito perigoso. Em seu livro Debugging Windows , John Robbins conta uma história de guerra sobre um bug realmente desagradável que foi mascarado por um comando catch (...). É muito melhor capturar exceções específicas. Pegue o que você acha que seu bloco try pode lançar razoavelmente, mas deixe o código lançar uma exceção mais alto se algo realmente inesperado acontecer.
fonte
Deixe-me mencionar isso aqui: o Java
NÃO pode pegar todas as exceções! Na verdade, já tive esse tipo de coisa antes, e é provocador de insanidade; A exceção deriva de Throwable. Então, literalmente, para capturar tudo, você NÃO deseja capturar Exceções; você quer pegar Throwable.
Eu sei que isso soa bem, mas quando você passa vários dias tentando descobrir de onde veio a "exceção não capturada" no código cercado por um bloco try ... catch (Exception e) ", ele fica com vocês.
fonte
catch(Exception)
pode não pegar todas as exceções em Java, você está misturando-o com C # ... Java =catch(Thowable)
, C # =catch(Exception)
. Não os confunda.CoderMalfunctionError
(que é realmente um verdadeiro JavaError
subclasse ... embora isso não significa o que parece.)Bem, se você quiser pegar todas as exceções para criar um minidump, por exemplo ...
Alguém fez o trabalho no Windows.
Consulte http://www.codeproject.com/Articles/207464/Exception-Handling-in-Visual-Cplusplus No artigo, ele explica como descobriu como capturar todos os tipos de exceções e fornece o código que funciona.
Aqui está a lista que você pode pegar:
E o uso: CCrashHandler ch; ch.SetProcessExceptionHandlers (); // faça isso para um thread ch.SetThreadExceptionHandlers (); // para cada thred
Por padrão, isso cria um minidump no diretório atual (crashdump.dmp)
fonte
Duvidoso. Você já sabe que seu código está quebrado, porque está travando. Exceções alimentares podem mascarar isso, mas isso provavelmente resultará em bugs ainda mais desagradáveis e sutis.
O que você realmente quer é um depurador ...
fonte
Você pode executar seu aplicativo Java usando JNI a partir de uma janela do console (inicie-o a partir de uma linha de comandos java) para ver se há algum relatório do que pode ter sido detectado antes do travamento da JVM. Ao executar diretamente como um aplicativo de janela Java, pode haver mensagens ausentes que apareceriam se você executasse a partir de uma janela do console.
Em segundo lugar, você pode stub sua implementação da DLL JNI para mostrar que os métodos na DLL estão sendo inseridos na JNI, você está retornando corretamente, etc.?
Caso o problema ocorra com o uso incorreto de um dos métodos da interface JNI do código C ++, você verificou se alguns exemplos simples de JNI são compilados e funcionam com sua configuração? Estou pensando em particular no uso dos métodos da interface JNI para converter parâmetros em formatos C ++ nativos e transformar resultados de funções em tipos Java. É útil stub-las para garantir que as conversões de dados estejam funcionando e que você não esteja distraído nas chamadas do tipo COM na interface JNI.
Há outras coisas a serem verificadas, mas é difícil sugerir alguma, sem saber mais sobre quais são seus métodos Java nativos e o que a implementação JNI deles está tentando fazer. Não está claro que a captura de uma exceção no nível do código C ++ esteja relacionada ao seu problema. (Você pode usar a interface JNI para refazer a exceção como Java, mas não está claro pelo que você fornece que isso ajudará.)
fonte
Para o problema real de não conseguir depurar corretamente um programa que usa JNI (ou o erro não aparece ao executá-lo em um depurador):
Nesse caso, geralmente ajuda a adicionar wrappers Java nas chamadas JNI (ou seja, todos os métodos nativos são privados e os métodos públicos da classe os chamam) que realizam algumas verificações básicas de integridade (verifique se todos os "objetos" estão liberados e "objetos" não são usados após a liberação) ou sincronização (apenas sincronize todos os métodos de uma DLL para uma instância de objeto único). Deixe os métodos do wrapper java registrarem o erro e lançarem uma exceção.
Isso geralmente ajuda a encontrar o erro real (que surpreendentemente está principalmente no código Java que não obedece à semântica das funções chamadas, causando algumas liberações duplas ou similares desagradáveis) mais facilmente do que tentar depurar um programa Java massivamente paralelo em um depurador nativo ...
Se você souber a causa, mantenha o código nos métodos do invólucro que o evitam. É melhor que seus métodos de wrapper gerem exceções que seu código JNI trava a VM ...
fonte
Bem, isso realmente depende do ambiente do compilador. O gcc não os captura. O Visual Studio e o último Borland que eu usei fizeram.
Portanto, a conclusão sobre falhas é que depende da qualidade do seu ambiente de desenvolvimento.
A especificação C ++ diz que catch (...) deve capturar qualquer exceção, mas não ocorre em todos os casos.
Pelo menos do que eu tentei.
fonte
Estar ciente
captura apenas exceções no nível do idioma, outras exceções / erros de baixo nível como
Access Violation
eSegmentation Fault
não serão detectadas.fonte