Exemplo
int *ptr;
*ptr = 1000;
posso capturar exceção de violação de acesso à memória usando C ++ padrão sem usar qualquer microsoft específico.
Exemplo
int *ptr;
*ptr = 1000;
posso capturar exceção de violação de acesso à memória usando C ++ padrão sem usar qualquer microsoft específico.
Respostas:
Não. C ++ não lança uma exceção quando você faz algo ruim, o que causaria um impacto no desempenho. Coisas como violações de acesso ou divisão por zero erros são mais como exceções de "máquina", em vez de coisas no nível da linguagem que você pode capturar.
Leia e chore!
Eu descobri. Se você não lançar do manipulador, o manipulador apenas continuará e também a exceção.
A mágica acontece quando você lança sua própria exceção e lida com isso.
#include "stdafx.h"
#include <stdio.h>
#include <stdlib.h>
#include <signal.h>
#include <tchar.h>
void SignalHandler(int signal)
{
printf("Signal %d",signal);
throw "!Access Violation!";
}
int main()
{
typedef void (*SignalHandlerPointer)(int);
SignalHandlerPointer previousHandler;
previousHandler = signal(SIGSEGV , SignalHandler);
try{
*(int *) 0 = 0;// Baaaaaaad thing that should never be caught. You should write good code in the first place.
}
catch(char *e)
{
printf("Exception Caught: %s\n",e);
}
printf("Now we continue, unhindered, like the abomination never happened. (I am an EVIL genius)\n");
printf("But please kids, DONT TRY THIS AT HOME ;)\n");
}
sigaltstack
) instalado (a menos que a implementação de desenrolamento de exceção C ++ permita), e cada função de tempo de execução que manipula o próprio mecanismo de desenrolamento deve ser seguro para sinais.
signal(SIGSEGV, SIG_DFL);
Há uma maneira muito fácil de capturar qualquer tipo de exceção (divisão por zero, violação de acesso, etc.) no Visual Studio usando o bloco try -> catch (...). Um pequeno ajuste nas configurações do projeto é o suficiente. Basta habilitar a opção / EHa nas configurações do projeto. Consulte Propriedades do projeto -> C / C ++ -> Geração de código -> Modifique a opção Ativar exceções C ++ para "Sim com exceções SEH" . É isso aí!
Veja os detalhes aqui: http://msdn.microsoft.com/en-us/library/1deeycx5(v=vs.80).aspx
Pelo menos para mim, a signal(SIGSEGV ...)
abordagem mencionada em outra resposta não funcionou no Win32 com Visual C ++ 2015 . O que funcionou para mim foi usar _set_se_translator()
found in eh.h
. Funciona assim:
Etapa 1 ) Certifique-se de habilitar Yes with SEH Exceptions (/ EHa) em Project Properties / C ++ / Code Generation / Enable C ++ Exceptions , conforme mencionado na resposta de Volodymyr Frytskyy .
Etapa 2 ) Chame _set_se_translator()
, passando um ponteiro de função (ou lambda) para o novo tradutor de exceção . É chamado de tradutor porque basicamente pega a exceção de baixo nível e a re-lança como algo mais fácil de detectar, como std::exception
:
#include <string>
#include <eh.h>
// Be sure to enable "Yes with SEH Exceptions (/EHa)" in C++ / Code Generation;
_set_se_translator([](unsigned int u, EXCEPTION_POINTERS *pExp) {
std::string error = "SE Exception: ";
switch (u) {
case 0xC0000005:
error += "Access Violation";
break;
default:
char result[11];
sprintf_s(result, 11, "0x%08X", u);
error += result;
};
throw std::exception(error.c_str());
});
Etapa 3 ) Capture a exceção como faria normalmente:
try{
MakeAnException();
}
catch(std::exception ex){
HandleIt();
};
Esse tipo de situação depende da implementação e, conseqüentemente, exigirá um mecanismo específico do fornecedor para fazer o trap. Com a Microsoft, isso envolverá SEH, e * nix envolverá um sinal
Em geral, capturar uma exceção de violação de acesso é uma ideia muito ruim. Quase não há maneira de se recuperar de uma exceção AV e tentar fazer isso apenas tornará mais difícil encontrar bugs no seu programa.
Conforme declarado, não existe uma maneira que não seja da Microsoft / fornecedor de compilador de fazer isso na plataforma Windows. No entanto, é obviamente útil capturar esses tipos de exceções na maneira normal try {} catch (exception ex) {} para relatórios de erros e mais uma saída elegante de seu aplicativo (como diz JaredPar, o aplicativo agora provavelmente está com problemas) . Usamos _se_translator_function em um wrapper de classe simples que nos permite capturar as seguintes exceções em um manipulador try:
DECLARE_EXCEPTION_CLASS(datatype_misalignment)
DECLARE_EXCEPTION_CLASS(breakpoint)
DECLARE_EXCEPTION_CLASS(single_step)
DECLARE_EXCEPTION_CLASS(array_bounds_exceeded)
DECLARE_EXCEPTION_CLASS(flt_denormal_operand)
DECLARE_EXCEPTION_CLASS(flt_divide_by_zero)
DECLARE_EXCEPTION_CLASS(flt_inexact_result)
DECLARE_EXCEPTION_CLASS(flt_invalid_operation)
DECLARE_EXCEPTION_CLASS(flt_overflow)
DECLARE_EXCEPTION_CLASS(flt_stack_check)
DECLARE_EXCEPTION_CLASS(flt_underflow)
DECLARE_EXCEPTION_CLASS(int_divide_by_zero)
DECLARE_EXCEPTION_CLASS(int_overflow)
DECLARE_EXCEPTION_CLASS(priv_instruction)
DECLARE_EXCEPTION_CLASS(in_page_error)
DECLARE_EXCEPTION_CLASS(illegal_instruction)
DECLARE_EXCEPTION_CLASS(noncontinuable_exception)
DECLARE_EXCEPTION_CLASS(stack_overflow)
DECLARE_EXCEPTION_CLASS(invalid_disposition)
DECLARE_EXCEPTION_CLASS(guard_page)
DECLARE_EXCEPTION_CLASS(invalid_handle)
DECLARE_EXCEPTION_CLASS(microsoft_cpp)
A classe original veio deste artigo muito útil:
Não é o mecanismo de tratamento de exceção, mas você pode usar o mecanismo signal () que é fornecido pelo C.
> man signal
11 SIGSEGV create core image segmentation violation
Escrever para um ponteiro NULL provavelmente causará um sinal SIGSEGV
signal()
faz parte do padrão posix. Windows implementa o padrão posix (assim como Linux e unix)
Uma violação como essa significa que há algo muito errado com o código e ele não é confiável. Eu posso ver que um programa pode querer tentar salvar os dados do usuário de uma forma que se espere não sobrescrever os dados anteriores, na esperança de que os dados do usuário já não estejam corrompidos, mas por definição não existe um método padrão de lidar com comportamento indefinido.