2010-07-22 6 views

Respuesta

26

No deberías. Una infracción de acceso es un problema grave: es un intento inesperado de escribir (o leer) una dirección de memoria no válida. Como John ya aclaró, la DLL no administrada podría haber corrompido la memoria del proceso antes de que se haya producido la violación de acceso. Esto puede tener efectos imprevistos en cualquier parte del proceso actual.

Lo más seguro es informar posiblemente al usuario y luego salir inmediatamente.

Algunos más detalles: una infracción de acceso es una excepción de sistema operativo (una llamada SEH o excepción de gestión estructurada excepción). Este es un tipo diferente de excepción que las excepciones gestionadas de CLR desde System.Exception. Raramente verá excepciones SEH en código puramente administrado, pero si se produce uno, p. en código no administrado, el CLR lo entregará al código administrado donde también puede atraparlo .

Sin embargo, la captura de excepciones de SEH generalmente no es una buena idea. Más detalles se explican en el artículo Handling Corrupted State Exceptions en la revista de MSDN donde el texto que sigue tomada de:

El CLR se caracteriza por ofrecer excepciones SEH a código administrado utilizando los mismos mecanismos que las excepciones planteadas por el propio programa. Esto no es un problema, siempre y cuando el código no intente manejar condiciones excepcionales que no pueda manejar razonablemente. La mayoría de los programas no pueden continuar de forma segura después de una violación de acceso. Desafortunadamente, el modelo de manejo de excepciones del CLR siempre ha alentado a los usuarios a detectar estos errores graves al permitir que los programas capten cualquier excepción en la parte superior de la jerarquía System.Exception. Pero esto rara vez es lo correcto.

Este fue el caso hasta .NET 3.5. En .NET 4, el comportamiento ha cambiado. Si aún desea poder obtener este tipo de excepciones, deberá agregar legacyCorruptedState­­ExceptionsPolicy=true a la app.config. Más detalles en el articulado vinculado anteriormente.

+4

Para aclarar: la razón por la que desea salir lo antes posible es que no sabe qué fue lo que sobrescribió la DLL no administrada antes de que golpee la Infracción de acceso. Puede haber estado escribiendo basura en lugares suficientes para que su programa no pueda continuar de manera segura. –

+0

@ John Saunders: Gracias por la aclaración. Actualicé mi respuesta. –

+4

Se me ocurre una muy buena razón para captar esto: si tiene un proceso no tripulado y no lo tiene, en lugar de salir, el proceso se bloqueará con el cuadro de diálogo Infracción de acceso que muestra a nadie en particular. Al capturar esto, puede salir sin que aparezca ese cuadro de diálogo. – jpwkeeper

0

puede envolver la llamada a la DLL no administrada con un bloque try-catch. AccessViolationExceptions se puede atrapar normalmente. Ejecutar el código siguiente muestra las dos mensajes:

try 
{ 
    throw new AccessViolationException(); 
} 
catch (Exception e) 
{ 
    MessageBox.Show(e.Message + e.StackTrace, e.Message, MessageBoxButtons.OK, MessageBoxIcons.Error); 
} 
MessageBox.Show("Still running.."); 

Editar: .NET 4 introdujo un change in behavior, ya no es posible capturar las excepciones estatales corruptos a menos que específicamente "ask" el tiempo de ejecución así lo indiquen.

+0

La pregunta es, ¿es una buena idea hacerlo? Puede ser sensato mostrar un mensaje agradable y amigable al usuario y escribir un registro. Pero trabajar más allá de eso no es una buena idea ... – rioki

+0

Probablemente no, al menos no si no estás absolutamente seguro de que no pasó nada malo. – andyp

+2

Eso no funciona. Intenté capturar Exception y AccessViolationException, pero ignora mi catch block. Supongo que hay alguna bandera de app.config que necesito. –

1

En primer lugar estoy totalmente de acuerdo con 0xA3. Pero si no hay salida, puede envolver el dll sucia no administrado en su propio proceso y transferir datos a través de IPC (TCP/IP, namedipes, etc.). Captura todas las excepciones e informa el proceso de host. Por lo tanto, su proceso de host es principalmente salvar de la corrupción de la memoria.

6

Sí.

En su aplicación.confg, plop el siguiente código dentro de la etiqueta <configuration>:

<runtime> 
    <legacyCorruptedStateExceptionsPolicy enabled="true"/> 
</runtime> 

Ahora usted debería ser capaz de capturar las excepciones estatales corruptos (CSE) como cualquier otro.

Nota: Si ya tiene una etiqueta de tiempo de ejecución a continuación, sólo tiene que añadir a ella <legacyCorruptedStateExceptionsPolicy enabled="true"/>

Los trabajos anteriores para .Net 4.5

+1

th para esto. Leí un par de respuestas a este problema. todos diciendo "add' 'to' app.config' "pero nadie dijo que no debería estar en la sección' 'predeterminada. Gracias por la pista con la sección '' – user1234

2

Como otros señalaron, no se debe "manejar" esta condición, pero durante el desarrollo, es útil detectar esto por el bien de la resolución de problemas.

Usted puede marcar su método de gestión con el atributo System.Runtime.ExceptionServices.HandleProcessCorruptedStateExceptions:

[HandleProcessCorruptedStateExceptions] 
public void MyMethod() 
{ 
    try 
    { 
     NaughtyCall(); 
    } 
    catch (AccessViolationException e) 
    { 
     // You should really terminate your application here 
    } 
} 
Cuestiones relacionadas