¿Captura excepciones de violación de acceso?

Ejemplo

int *ptr; *ptr = 1000; 

¿Puedo atrapar la excepción de violación de acceso a memoria usando C ++ estándar sin usar ningún microsoft específico?

Nop. C ++ no lanza una excepción cuando haces algo malo, que incurriría en un golpe de rendimiento. Cosas como violaciones de acceso o división por errores cero son más como excepciones de “máquina”, en lugar de cosas de nivel de lenguaje que puede atrapar.

¡Léelo y llora!

Me lo imaginé. Si no tira desde el controlador, el controlador continuará y también la excepción.

La magia sucede cuando lanzas tu propia excepción y manejas eso.

 #include "stdafx.h" #include  #include  #include  #include  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"); } 

Hay una manera muy fácil de detectar cualquier tipo de excepción (división por cero, violación de acceso, etc.) en Visual Studio usando try -> catch (…) block. Un ajuste de configuración de proyecto menor es suficiente. Simplemente habilite la opción / EHa en la configuración del proyecto. Ver Propiedades del proyecto -> C / C ++ -> Generación de código -> Modificar las excepciones Habilitar C ++ a “Sí con excepciones SEH” . ¡Eso es!

Vea los detalles aquí: http://msdn.microsoft.com/en-us/library/1deeycx5(v=vs.80).aspx

Este tipo de situación depende de la implementación y, en consecuencia, requerirá un mecanismo específico del proveedor para atrapar. Con Microsoft esto implicará SEH, y * nix implicará una señal

En general, aunque atrapar una excepción de Infracción de acceso es una muy mala idea. Casi no hay forma de recuperarse de una excepción de AV e intentar hacerlo dificultará la búsqueda de errores en su progtwig.

Como se indicó, no existe una forma de proveedor que no sea de Microsoft / comstackdor para hacer esto en la plataforma de Windows. Sin embargo, obviamente es útil detectar este tipo de excepciones en la forma normal try {} catch (excepción ex) {} para informar errores y más una salida elegante de su aplicación (como dice JaredPar, la aplicación probablemente ahora esté en problemas) . Usamos _se_translator_function en un contenedor de clase simple que nos permite capturar las siguientes excepciones en un manejador de prueba:

 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) 

La clase original vino de este artículo muy útil:

http://www.codeproject.com/KB/cpp/exception.aspx

Al menos para mí, el enfoque de signal(SIGSEGV ...) mencionado en otra respuesta no funcionó en Win32 con Visual C ++ 2015 . Lo que funcionó para mí fue usar _set_se_translator() encuentra en eh.h Funciona así:

Paso 1 ) Asegúrese de habilitar Sí con excepciones SEH (/ EHa) en Propiedades del proyecto / C ++ / Generación de código / Habilitar excepciones de C ++ , como se menciona en la respuesta de Volodymyr Frytskyy .

Paso 2 ) Llame a _set_se_translator() , pasando un puntero de función (o lambda) para el nuevo traductor de excepciones. Se llama un traductor porque básicamente solo toma la excepción de bajo nivel y la vuelve a lanzar como algo más fácil de detectar, como std::exception :

 #include  #include  // 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()); }); 

Paso 3 ) Captura la excepción como lo harías normalmente:

 try{ MakeAnException(); } catch(std::exception ex){ HandleIt(); }; 

No es el mecanismo de manejo de excepciones, pero puede usar el mecanismo de señal () proporcionado por C.

 > man signal 11 SIGSEGV create core image segmentation violation 

Escribir en un puntero NULL probablemente genere una señal SIGSEGV

Una violación como esa significa que hay algo muy mal con el código, y no es confiable. Veo que un progtwig podría intentar guardar los datos del usuario de una manera que uno espera que no escriba datos anteriores, con la esperanza de que los datos del usuario no estén ya dañados, pero por definición no hay un método estándar. de lidiar con un comportamiento indefinido.