Delen via


reentrancy MDA

Notitie

Dit artikel is specifiek voor .NET Framework. Dit geldt niet voor nieuwere implementaties van .NET, waaronder .NET 6 en nieuwere versies.

De reentrancy beheerde foutopsporingsassistent (MDA) wordt geactiveerd wanneer een poging wordt gedaan om over te stappen van systeemeigen naar beheerde code in gevallen waarin een eerdere overstap van beheerde naar systeemeigen code niet is uitgevoerd via een ordelijke overgang.

Symptomen

De object-heap is beschadigd of er treden andere ernstige fouten op bij het overstappen van systeemeigen naar beheerde code.

Threads die schakelen tussen systeemeigen en beheerde code in beide richtingen, moeten een ordelijke overgang uitvoeren. Bepaalde uitbreidbaarheidspunten op laag niveau in het besturingssysteem, zoals de vectored exception handler, staan schakelopties toe van beheerde naar systeemeigen code zonder een ordelijke overgang uit te voeren. Deze switches vallen onder besturingssysteembeheer, in plaats van onder CLR-beheer (Common Language Runtime). Systeemeigen code die in deze uitbreidbaarheidspunten wordt uitgevoerd, moet voorkomen dat u terugroept naar beheerde code.

Oorzaak

Een uitbreidbaar besturingssysteempunt op laag niveau, zoals de vectored exception handler, is geactiveerd tijdens het uitvoeren van beheerde code. De toepassingscode die via dat uitbreidbaarheidspunt wordt aangeroepen, probeert terug te roepen naar beheerde code.

Dit probleem wordt altijd veroorzaakt door toepassingscode.

Oplossing

Bekijk de stacktracering voor de thread die deze MDA heeft geactiveerd. De thread probeert illegaal aan te roepen in beheerde code. De stacktracering moet de toepassingscode onthullen met behulp van dit uitbreidbaarheidspunt, de besturingssysteemcode die dit uitbreidbaarheidspunt biedt en de beheerde code die is onderbroken door het uitbreidbaarheidspunt.

U ziet bijvoorbeeld dat de MDA is geactiveerd in een poging om beheerde code aan te roepen vanuit een vectored uitzonderingshandler. Op de stack ziet u de uitzonderingsverwerkingscode van het besturingssysteem en een aantal beheerde code die een uitzondering activeert, zoals een DivideByZeroException of een AccessViolationException.

In dit voorbeeld is de juiste oplossing om de vectored exception handler volledig in onbeheerde code te implementeren.

Effect op de runtime

Deze MDA heeft geen effect op de CLR.

Uitvoer

De MDA meldt dat illegale reentrancy wordt geprobeerd. Bekijk de stack van de thread om te bepalen waarom dit gebeurt en hoe u het probleem kunt oplossen. Hieronder ziet u voorbeelduitvoer.

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'.

Configuratie

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

Opmerking

In het volgende codevoorbeeld wordt een AccessViolationException fout gegenereerd. In versies van Windows die vectored exception handling ondersteunen, zorgt dit ervoor dat de managed vectored exception handler wordt aangeroepen. Als de reentrancy MDA is ingeschakeld, wordt de MDA geactiveerd tijdens de poging om vanuit MyHandler de vectored exception handling code van het besturingssysteem te activeren.

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 { }
    }
}

Zie ook