Reentrancy

Actualización: noviembre 2007

El asistente para la depuración administrada (MDA) reentrancy se activa cuando se intenta realizar una transición desde código nativo a código administrado en los casos en los que no se realizó un cambio anterior a un código nativo mediante una transición ordenada.

Síntomas

El montón de objetos está dañado o se producen otros errores graves al realizar la transición de código nativo a código administrado.

Los subprocesos que cambian entre código nativo y administrado en cualquier dirección deben seguir una transición ordenada. Sin embargo, determinados puntos de extensibilidad de bajo nivel del sistema operativo, como el controlador de excepciones vectorizadas, permiten pasar de código administrado a código nativo sin realizar una transición ordenada. Estos cambios se realizan bajo el control de sistema operativo, en lugar de bajo el control de Common Language Runtime (CLR). Cualquier código nativo que se ejecute dentro de estos puntos de extensibilidad debe evitar las llamadas de vuelta al código administrado.

Motivo

Un punto de extensibilidad de sistema operativo de bajo nivel, como el controlador de excepciones vectorizadas, se ha activado al ejecutar el código administrado. El código de aplicación que se invoca a través de ese punto de extensibilidad está intentando llamar de vuelta al código administrado.

Este problema siempre está causado por el código de aplicación.

Resolución

Examine el seguimiento de la pila para conocer el subproceso que ha activado el MDA. El subproceso está intentando llamar al código administrado de manera no válida. El seguimiento de la pila debería mostrar el código de aplicación que utiliza este punto de extensibilidad, el código del sistema operativo que proporciona este punto de extensibilidad y el código administrado que interrumpió el punto de extensibilidad.

Por ejemplo, verá que se activa el MDA en un intento de llamar al código administrado desde dentro de un controlador de excepciones vectorizado. En la pila verá el código de control de excepciones del sistema operativo y parte del código administrado que desencadena una excepción como por ejemplo DivideByZeroException o AccessViolationException.

En este ejemplo, la resolución correcta consiste en implementar completamente el controlador de excepciones vectorizado en código no administrado.

Efecto en el tiempo de ejecución

Este MDA no tiene ningún efecto en CLR.

Resultados

El MDA informa de que se está intentando una reentrada no válida. Examine la pila del subproceso para determinar por qué ocurre esto y cómo corregir el problema. A continuación se incluyen resultados de ejemplo.

Additional Information: Attempting to call into managed code without 
transitioning out first.  Do not attempt to run managed code inside 
low-level native extensibility points. Managed Debugging Assistant 
'Reentrancy' has detected a problem in 'D:\ConsoleApplication1\
ConsoleApplication1\bin\Debug\ConsoleApplication1.vshost.exe'.

Configuración

<mdaConfig>
  <assistants>
    <reentrancy />
  </assistants>
</mdaConfig>

Ejemplo

En el ejemplo de código siguiente hace que se inicie una excepción AccessViolationException. En versiones de Windows que admiten el control de excepciones vectorizado, esto hará que se llame al controlador de excepciones vectorizado. Si está habilitado el MDA reentrancy, el MDA se activará durante el intento de llamada a MyHandler desde el código de compatibilidad del control de excepciones vectorizado del sistema operativo.

using System;
public delegate int ExceptionHandler(IntPtr ptrExceptionInfo);

public class Reenter 
{
    public static ExceptionHandler keepAlive;

    [System.Runtime.InteropServices.DllImport("kernel32", ExactSpelling=true, 
        CharSet=System.Runtime.InteropServices.CharSet.Auto)]
    public static extern IntPtr AddVectoredExceptionHandler(int bFirst, 
        ExceptionHandler handler);

    static int MyHandler(IntPtr ptrExceptionInfo) 
    {
        // EXCEPTION_CONTINUE_SEARCH
        return 0;
    }
    void Run() {}

    static void Main() 
    {
        keepAlive = new ExceptionHandler(Reenter.MyHandler);
        IntPtr ret = AddVectoredExceptionHandler(1, keepAlive);
        try 
        {
            // Dispatch on null should AV.
            Reenter r = null; 
            r.Run();
        } 
        catch { }
    }
}

Vea también

Conceptos

Diagnóstico de errores con ayudantes de depuraciones administradas