Ejemplo
int *ptr;
*ptr = 1000;
¿Puedo detectar una excepción de infracción de acceso a la memoria usando C ++ estándar sin usar ningún microsoft específico?
c++
exception-handling
Ahmed dijo
fuente
fuente
¡Léelo y llora!
Me lo imaginé. Si no lanza desde el controlador, el controlador simplemente continuará y también lo hará la excepción.
La magia ocurre cuando lanzas tu propia excepción y manejas eso.
#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"); }
fuente
sigaltstack
) instalada (a menos que la implementación de desenrollado de excepción de C ++ lo permita), y cada función de tiempo de ejecución que maneja el mecanismo de desenrollado debe ser segura para señales.signal(SIGSEGV, SIG_DFL);
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 el bloque try -> catch (...). Un pequeño ajuste de la configuración del proyecto es suficiente. Simplemente habilite la opción / EHa en la configuración del proyecto. Consulte Propiedades del proyecto -> C / C ++ -> Generación de código -> Modifique Habilitar excepciones C ++ a "Sí con excepciones SEH" . ¡Eso es!
Vea los detalles aquí: http://msdn.microsoft.com/en-us/library/1deeycx5(v=vs.80).aspx
fuente
Al menos para mí, el
signal(SIGSEGV ...)
enfoque mencionado en otra respuesta no funcionó en Win32 con Visual C ++ 2015 . Lo que funcionó para mí fue usar_set_se_translator()
encontrado eneh.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 C ++ , como se menciona en la respuesta de Volodymyr Frytskyy .
Paso 2 ) Llame
_set_se_translator()
, pasando un puntero de función (o lambda) para el nuevo traductor de excepciones . Se llama traductor porque básicamente solo toma la excepción de bajo nivel y la vuelve a lanzar como algo más fácil de atrapar, comostd::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()); });
Paso 3 ) Capture la excepción como lo haría normalmente:
try{ MakeAnException(); } catch(std::exception ex){ HandleIt(); };
fuente
Este tipo de situación depende de la implementación y, en consecuencia, requerirá un mecanismo específico del proveedor para realizar la captura. Con Microsoft esto involucrará SEH, y * nix involucrará una señal
En general, detectar 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 solo hará que sea más difícil encontrar errores en su programa.
fuente
Como se indicó, no existe una forma que no sea de Microsoft / proveedor de compiladores para hacer esto en la plataforma Windows. Sin embargo, obviamente es útil detectar este tipo de excepciones de la manera normal try {} catch (excepción ex) {} para informar de errores y más una salida elegante de su aplicación (como dice JaredPar, la aplicación ahora probablemente tenga problemas) . Usamos _se_translator_function en un contenedor de clase simple que nos permite capturar las siguientes excepciones en un controlador de prueba:
La clase original provino de este artículo muy útil:
http://www.codeproject.com/KB/cpp/exception.aspx
fuente
No es el mecanismo de manejo de excepciones, pero puede usar el mecanismo signal () proporcionado por C.
> man signal 11 SIGSEGV create core image segmentation violation
Escribir en un puntero NULL probablemente provocará una señal SIGSEGV
fuente
signal()
es parte del estándar posix. Windows implementa el estándar posix (al igual que Linux y Unix)Una infracción como esa significa que hay algo muy mal con el código y no es confiable. Puedo ver que un programa puede querer intentar guardar los datos del usuario de una manera que uno espera que no se escriban sobre los datos anteriores, con la esperanza de que los datos del usuario no estén ya corruptos, pero por definición no existe un método estándar. de lidiar con un comportamiento indefinido.
fuente