2009-02-12 12 views
12

Como dice el título, estamos buscando una forma de detectar todas las excepciones de un fragmento de código C++ y envolverlo en un dll. De esta forma podemos proteger de la aplicación que usa este dll, de cualquier error que ocurra en este dll.¿Cómo crear un contenedor C++ Dll que capte todas las excepciones?

Sin embargo, esto no parece posible con C++ en Windows.

Ejemplo:

void function() 
{ 
    try 
    {  
     std::list<int>::iterator fd_it; 
     fd_it++; 
    } catch(...) {} 
} 

La excepción que se produce no es atrapado por el estándar C++ tratar/bloque catch, ni por cualquier función traductor SEH establecido por _set_se_translator(). En cambio, el DLL se bloquea y el programa que usa el DLL se cancela. Compilamos con Visual C++ 2005, con la opción/SHa. ¿Alguien sabe si es posible en C++/Win32 detectar este tipo de problemas y crear un contenedor DLL sólido?

+1

Igual que [C++ detecta todas las excepciones] (http://stackoverflow.com/questions/315948/c-catching-all-exceptions) – lsalamon

Respuesta

4

Incrementar un iterador en un contenedor de libary estándar nunca lanzará una excepción de C++. Puede darte un comportamiento indefinido.

+1

Puede lanzar una excepción estructurada que es una cosa del compilador de Microsoft. Con ellos, puedes capturar las divisiones por cero, mal acceso a la memoria, etc. La semántica es diferente a las excepciones de C++. – Aardvark

+2

Cuál es comportamiento indefinido de una perspectiva estándar de C+++ –

+0

Claro, seguro que no estaba en desacuerdo. Solo señalando en VC++ arrojará algo que puede ser atrapado por catch (...). Pero esto no es estándar C++ de ninguna manera. – Aardvark

8

En Windows, C++ tiene 2 estilos diferentes de excepciones: excepciones C++ y SEH.

SEH es una forma de excepción de Windows (algo similar a similar a las señales en UNIX). Es más una excepción de nivel de sistema. Serán arrojados para operaciones tales como accesos de puntero no válidos, problemas de alineación, etc. ...

Si quiere ver todas las excepciones que puede lanzar una aplicación C++ en Windows, necesitará capturar ambas. Afortunadamente, hay una manera de mezclar el uso de las excepciones C++ y SEH. Escribí una publicación detallada del blog sobre esto recientemente, debería ayudarte.

http://blogs.msdn.com/jaredpar/archive/2008/01/11/mixing-seh-and-c-exceptions.aspx

1

¿Has mirado en la función SetUnhandledExceptionFilter API de Windows?

Normalmente lo llamo en la función DllMain y hago que genere un minivolcado cuando el DLL se cuelga. Sin embargo: (a) no sé si atrapa las excepciones de aplicación y las excepciones de DLL, y (b) no sé si puede hacer que el controlador regrese de tal forma que la ejecución del programa pueda continuar. Los documentos dicen que sí, pero nunca lo hice.

22

La única manera de hacer un contenedor DLL sólido como una roca es cargar la DLL con errores en otro proceso, por lo que si se bloquea no se lleva consigo el proceso primario.

La captura de todas las excepciones de C++ parece razonable, pero atrapar todas las excepciones estructuradas es otra historia. SEH podría parecer para conseguir que la mayor parte del camino, ya que le permite ponerse al violaciónes de acceso, de división por cero excepciones, etc.

Pero lo que si el buggy DLL pasa a tocar una página no comprometidos de otro pila de hilos? El acceso a la memoria generará un error de página, se invocará al controlador de excepción y ahora esa página ya no es una página de protección. Cuando ese hilo necesite aumentar la pila, obtendrá una violación de acceso y el proceso se bloqueará. (Theseposts describa este caso con más detalle.)

Otro problema probable: el DLL defectuoso falla al mantener un objeto de sincronización, pero utiliza SEH para capturar la excepción. Si su proceso intenta adquirir el mismo objeto de sincronización, se bloquea en lugar de bloquearse.El objeto de sincronización compartida puede ser parte del tiempo de ejecución de C o del sistema operativo: ¿qué ocurre si el archivo DLL 1 con errores carga DLL 2 con errores, que se bloquea en su DllMain() mientras DLL 1 con errores mantiene el bloqueo del cargador? ¿Su proceso se estancará la próxima vez que cargue una DLL?

Para obtener más información sobre por qué esto (y funciona como IsBadReadPtr(), que tienen problemas similares) es un mal uso de la SEH:

4

Este código contiene un error de lógica, en todo caso. Dado que un error de lógica constituye un error, no trague la excepción: solucione el error!

Por supuesto, esto es específico para el código en particular. Otros han ofrecido un consejo más general. Sin embargo, he encontrado que mucha gente realmente do prefiere capturar excepciones sobre la fijación de errores lógicos y esto es simplemente inaceptable.

4

El código siguiente está tomado del Zeus IDE. Será trampa de cualquier Windows generada excepciones:

Paso # 1: definir una función Excepción Filtro

DWORD ExceptionFilter(EXCEPTION_POINTERS *pointers, DWORD dwException) 
    { 
    //-- we handle all exceptions 
    DWORD dwResult = EXCEPTION_EXECUTE_HANDLER; 

    switch (dwException) 
    { 
     case EXCEPTION_ACCESS_VIOLATION: 
     case EXCEPTION_DATATYPE_MISALIGNMENT: 
     case EXCEPTION_ARRAY_BOUNDS_EXCEEDED: 
     case EXCEPTION_FLT_DENORMAL_OPERAND: 
     case EXCEPTION_FLT_DIVIDE_BY_ZERO: 
     case EXCEPTION_FLT_INEXACT_RESULT: 
     case EXCEPTION_FLT_INVALID_OPERATION: 
     case EXCEPTION_FLT_OVERFLOW: 
     case EXCEPTION_FLT_STACK_CHECK: 
     case EXCEPTION_FLT_UNDERFLOW: 
     case EXCEPTION_INT_DIVIDE_BY_ZERO: 
     case EXCEPTION_INT_OVERFLOW: 
     case EXCEPTION_PRIV_INSTRUCTION: 
     case EXCEPTION_NONCONTINUABLE_EXCEPTION: 
     case EXCEPTION_BREAKPOINT: 
     dwResult = EXCEPTION_EXECUTE_HANDLER; 
     break; 
    } 

    return dwResult; 
    } 

Paso # 2: ajustar el código en un __try y __except como se muestra a continuación:

__try 
    { 
    // call your dll entry point here 
    } 
    __except(ExceptionFilter(GetExceptionInformation(), 
          GetExceptionCode())) 
    { 
    //-- display the fatal error message 
    MessageBox(0, "An unexpected error was caught here!", 
       "Unexpected Error", MB_OK); 
    } 
1

¿Qué vas a hacer después de atrapar la excepción? (especialmente para excepciones SEH)?

En realidad, no puede hacer suposiciones sobre el estado del proceso, de manera realista la única opción que tiene es (opcionalmente) volcar núcleo y salir.

Cualquier intento y procedimiento definitivamente le causará problemas a largo plazo.

3

Konrad Rudolph: Por supuesto, este código contiene un "error de lógica", es para ilustrar un problema que podría ocurrir. Al igual que el hombre dice que quiere ser capaz de proteger su dll de posibles errores. ¿No crees que esta es una pregunta legítima? Oído de los productos del vendedor. Algunos de nosotros vivimos en el mundo real y vivimos con problemas reales. Simplemente no es posible solucionar los problemas de los demás

Cuestiones relacionadas