Frage

Ich habe einen ungewöhnlichen Fall, in dem ich eine sehr einfache Ausnahme habe, die in dieselbe Methode geworfen und gefangen werde. Es wird nicht wiedergeworfen (Die übliche Art von Problem naive Programmierer haben). Und doch enthält sein Stackframe nur einen der aktuellen Methode. So sieht es aus:

   at (my class).MyMethod() in C:\(my file path and line)

In Wirklichkeit gibt es wahrscheinlich 30 Methoden, die im Call -Stack des VS2010 -Debuggers dazu führen, ein halbes Dutzend verschiedene Versammlungen. Es scheint unmöglich, dass all das optimiert wurde. Darüber hinaus ist dieser Code integriert Debug -Modus ohne Optimierungen, für .net 4. Ich habe sogar (basierend auf http://msdn.microsoft.com/en-us/library/9dd8z24x.aspx) .ini -Dateien (einschließlich eines namens [App] .vshost.ini) in demselben Ordner mit:

[.NET Framework Debugging Control]
GenerateTrackingInfo=1
AllowOptimize=0

Außerdem stehen die Methodenaufrufe nicht am Ende der Methoden, daher erscheint die Optimierung der Schwanzrezidien weiter unwahrscheinlich.

Wie es genannt wird: Es gibt keine Reflexion im Anrufstapel, kein aufrufen () oder in jeglicher Art. Dies ist nur eine lange Kette von Anrufen aus einer Schaltfläche Klick. Der Klick -Handler ist ungefähr 10 Anrufe im Anrufstapel. Darunter haben Sie die üblichen WndProc, nativeWindow.callback, native/verwaltete Übergänge und Nachrichtenschleife. Dies liegt letztendlich in einem ShowDialog () -Anruf, der von einer C# EXE -Baugruppe ausgeführt wird.

Jetzt stellte ich fest, dass ich Instanzen der Stacktrace -Klasse in meinem Catch -Handler konstruieren kann, und wenn ich das Ausnahmebobjekt übertrage, ist auch der Anrufstapel kurz. Wenn ich stattdessen nur New Stacktrace () ohne Argumente rufe, ergibt es einen vollständigen Anrufstapel.

Ich habe Reflektor verwendet, um in die Interna der Ausnahmeklasse zu debuggen, die ausgeworfen und ihr Call Stack konstruiert wurde, aber ich konnte keine Haltepunkte in Ausnahme oder in Stacktrace festlegen. Ich könnte sie in Environgs einstellen. (Diese Methode wird jedoch für einige andere Dinge ausgelöst, daher bin ich mir nicht sicher, was ich daraus machen soll.)

Hier ist ein Auszug der Methode:

private void MyMethod()
{
    ...               
    try
    {
        throw new ApplicationException("Test failure");
    }
    catch (Exception e)
    {
        StackTrace stackTrace1 = new StackTrace(e);
        StackTrace stackTrace2 = new StackTrace(e, false);
        StackTrace stackTrace3 = new StackTrace(e, true);
        StackTrace stackTrace4 = new StackTrace();
        string STs = stackTrace1.ToString() + "\n---\n"
            + stackTrace2.ToString() + "\n---\n"
            + stackTrace3.ToString() + "\n---\n"
            + stackTrace4.ToString();
        Log(EventSeverity.Debug, STs);
        ...
        }
    }

Es ist wirklich ziemlich einfach: Ausnahme, fangen und protokollieren Sie es.

Ich bekomme die gleichen Ergebnisse entweder im Debugger oder beim Ausführen von Standalone-ein Einzeilen-Anrufstack. Und ich weiß, dass ich dieses Problem an anderer Stelle in unserer Codebasis gesehen habe. Zuvor hatte ich angenommen, dass es an Ausnahmen zurückzuführen war, aber in vielen Fällen melden wir uns direkt im anfänglichen Fangblock an. Ich bin ziemlich verblüfft und die gesamte Websuche, die ich durchgeführt habe, hat nichts produziert.


Dies ist ein wenig zu viel als Kommentar zur Antwort hinzu, aber hier finden Sie einige weitere Informationen:

Ich sehe jetzt, dass dieses Verhalten bei besprochen wirdhttp://dotnethoughuts.wordpress.com/2007/10/27/where-did-my-exception-occur/ und dass es tatsächlich beschrieben wird bei http://msdn.microsoft.com/en-us/library/system.exception.stacktrace.aspx (Obwohl ich denke, dass man leicht vermissen könnte, was sie dort sagen).

Ich denke, meine "Lösung" wird ein kleines Hit-or-Miss sein. Wir haben eine zentrale Methode, die wir normalerweise aufrufen, um Ausnahmen zu formatieren. In dieser Methode erstelle ich eine neue Stacktrace () mit und ohne Ausnahmebobjekt. Dann werde ich nach der Methode suchen, die am Ende der Stapelspur der Ausnahme liegt, und alles darunter in der neuen Stacktrace () anzeigen, was darauf hinweist, dass sie von dieser Reihe von Aufrufen genannt wurde.

Die Abwärtsseite ist natürlich, dass die Informationen nicht vorhanden sind, wenn diese Methode nicht verwendet wird. Aber ich musste irgendwo eine Art Code ändern.

War es hilfreich?

Lösung

Wenn eine Ausnahme ausgelöst wird, wird nur eine teilweise Stapelspur in der verwendet Exception.StackTrace Eigentum. Der Stapel zeigt nur Aufrufe an, bis die Methode, die die Ausnahme erwischt. Um den vollen Stack zu bekommen (wie Sie bemerkt haben), sollten Sie eine erstellen new StackTrace() Objekt.

Ich kann momentan keine Links finden, aber ich glaube, die Stapelspur wird gebaut, indem ich den Stapel hinaufgehe, während ich die Ausnahme auswirft. Sobald die Ausnahme einen Fangblock erreicht hat, wird der Stapel nicht mehr kompiliert. Deshalb bekommen Sie nur einen Teilstapel.

Normalerweise befasst sich ein Hakenblock nicht damit, wer ihn genannt hat, sondern woher die Ausnahme stammt.

Lizenziert unter: CC-BY-SA mit Zuschreibung
Nicht verbunden mit StackOverflow
scroll top