Einen kuriosen Fall von Visual Studio 2010 debugger(es kann nicht auf einen break-point)
Einem kuriosen Fall von Visual Studio 2010 debugger(es kann nicht auf einen break-Punkt)
Dies ist der code, der das problem reproduziert:
class Program {
static void Main(string[] args) {
bool b = false;
if (b) {
List<string> list = new List<string>();
foreach (var item in list) {
}
} else {
Console.WriteLine("1");
}
Console.WriteLine("2");//add a break point here in VS2010
}
//1. configuration: release
//2. platform target: x64 or Any Cpu
//3. debug info: pdb only or full
//4. OS: Win7 x64
//5. optimize code: enabled
}
Fügen Sie eine Pause, um die Letzte Anweisung aus code, dann debug es in vs2010, werden Sie sehen, dass der break-point kann nicht erreicht werden.
Reproduzieren diese merkwürdige Fall, müssen Sie die folgenden Bedingungen erfüllen:
- Betriebs-system: windows 7 x64;
- VS build-Konfiguration: release;
- VS build platform target: x64 oder Any Cpu;
- VS build-debug-info: pdb nur oder voll;
- VS build optimieren-code: aktiviert;
Ich bin nicht sicher, dass diese Bedingungen sind ausreichend, um es zu reproduzieren, aber es ist, wie meine Maschine so konfiguriert wurde, dass, wenn ich gefunden dieses Problem.
Warum ist der debugger nicht in der Lage, um den Haltepunkt erreicht?
Vielen Dank im Voraus!
Und wenn Sie sich reproduzieren können dieses Problem, bitte beachten Sie die Abstimmung über in diesem post.
- Ich habe diese Konfiguration und kann ich nicht reproduzieren Ihre angegebenen Verhalten. Würde es eine Rolle, dass ich mit Win7 64 Bit SP 1? Der rest der Einrichtung ist die gleiche, aber ich den Haltepunkt zu jeder Zeit.
- funktioniert Prima für mich - so oder so, warum sind Sie das debugging in den release-Modus?
- Ich Stelle mir die Strecke wurde optimiert durch den compiler, wenn Sie Schritt, ist es dann läuft die Konsole.writeline("1") doppelt, aber die Bereitstellung von verschiedenen Argumenten?
- Vermute, dass unter Freigabe können Sie nicht treffen, jeder Haltepunkt als debug-info ist nicht generiert.
- Nein, das habe ich versucht. Es trifft der Pause, solange es nicht die Letzte Anweisung.
- Nein, ich bin mit Win7 SP1 auch. Eigentlich bin ich nicht sicher, welche anderen Konfigurationen kann das Ergebnis beeinflussen.
- Ohne Grund, nur um das Spiel 🙂
- Nein, ich dekompiliert und sah den IL-code. Das ist wahrscheinlich nicht der Fall.
- Du hast Recht, es ist seltsam... wenn du den Haltepunkt auf der aktuelle Aufruf von WriteLine (in der disassembly-Ansicht), dann ist es nicht der hit, aber Sie haben zu halten, neuaktivieren es für jeden Lauf.
- Was ich denke, ist sogar odder, ist, wenn Sie duplizieren die Finale Konsole.WriteLine (kopieren Sie es auf der Linie unten), können Sie den Haltepunkt in der letzten, und es wird ein hit sein, aber die, die mit Ihrem derzeitigen Haltepunkt es immer noch nicht...
- Ja, ich habe bemerkt, dass auch. Es überspringt das erste Anweisung nach der if-else.
- Dies sieht wie ein job für connect.microsoft.com.
- Hamidi: vielen Dank für die Beratung. Ich poste diese Frage gibt.
Du musst angemeldet sein, um einen Kommentar abzugeben.
Als Beispiel ist gebaut im release-Modus und dann JIT-ed in 64-bit-Maschinen-code, es enthält nicht genügend Informationen für den debugger zum korrelieren der Haltepunkt mit einem bestimmten Maschinenbefehl. Deshalb debugger nie aufhört, an dieser Haltepunkt während der Ausführung von JIT-ed-Maschinen-code. Es funktioniert einfach nicht wissen, wo zu stoppen. Wahrscheinlich ist es eine Art von Fehlverhalten oder sogar ein bug in der 64-bit-CLR-debugger, da es reproduzierbar nur bei JIT-ed in 64-bit-Maschinen-code, aber nicht in 32-bit-Maschinen-code.
Wenn der debugger sieht einen Haltepunkt im code versucht, um herauszufinden, eine Maschine, die den Unterricht in den JIT-ed-code, entspricht der Standort geprägt durch den Haltepunkt. Erste, es zu finden, braucht ein IL-Anweisung entspricht einem breakpoint-Position in Ihrem C# - code. Dann muss man es finden, einem Maschinenbefehl entspricht, die IL-Befehl. Dann setzt es eine echte Haltepunkt an der gefundenen Maschine Anweisung und startet die Ausführung der Methode. In deinem Fall, sieht es wie, dass der debugger ignoriert einen Haltepunkt, weil es nicht zuordnen kann und einem bestimmten Maschinenbefehl.
Der debugger kann nicht finden, eine Adresse einer Maschinen-Instruktion, die unmittelbar folgt if...else-Anweisung. Die if...else-Anweisung, und der code innen ist es irgendwie verursacht dieses Verhalten. Es spielt keine Rolle, welche Erklärung folgt die if...else. Sie können ersetzen Sie die Konsole.WriteLine("2") - Anweisung mit einigen anderen ein, und Sie werden immer noch in der Lage das Problem zu reproduzieren.
Werden Sie sehen, dass der C# - compiler emittiert ein try...catch-block, um die Logik, die liest die Liste, wenn Sie zerlegen Sie die resultierende assembly mit Reflektor. Es ist ein dokumentiertes feature von C# - compiler. Lesen Sie mehr darüber auf Die foreach-Anweisung
Einen try...catch...finally-Blocks hat eine ziemlich invasive Wirkung auf eine JIT-ed-code. Es verwendet die Windows-SEH-Mechanismus unter der Haube und schreibt Ihren code schlecht. Ich kann nicht finden, ein link zu einem guten Artikel jetzt, aber ich bin mir sicher, Sie finden heraus dort, wenn Sie daran interessiert sind.
Ist es, was hier geschieht. Der try...finally-block innerhalb von if...else-Anweisung bewirkt, dass der debugger an Schluckauf. Sie reproduzieren können, Ihr Problem mit einem sehr einfachen code.
Dieser code nicht, rufen Sie eine externe Funktionen (es entfällt die Wirkung der Methode inlining vorgeschlagen, die von einer der Antworten) und kompiliert direkt in IL-ohne zusätzliche codierte Hinzugefügt, die vom C# - compiler.
Es ist reproduzierbar nur im release-Modus, denn in den debug-Modus der compiler gibt die IL NOP-Anweisung für jede Zeile, die von Ihrem C# - code. Die IL NOP-Anweisung tut nichts, und es ist direkt kompiliert, um die CPU NOP Anweisung des JITer, die nichts tut, auch. Der nutzen dieser Anweisung ist, dass es verwendet werden kann, die durch den debugger als einen Anker für die Haltepunkte, auch wenn der rest des Codes ist schlecht umgeschrieben von den JITer.
Konnte ich den debugger richtig funktioniert, indem Sie eine NOP-Anweisung direkt vor die Anweisung nach der if...else.
Lesen Sie mehr über NOP-Operationen und debugger mapping-Prozess hier Debugging-IL
Können Sie versuchen, verwenden Sie WinDbg und SOS-Erweiterung für es zu untersuchen, JIT-ed-version der Methode. Sie können versuchen, zu untersuchen, Maschinen-code, der JIT-er generiert und versuchen zu verstehen, warum es keine Karte zurück, die Maschine code, um bestimmte Zeile von C#.
Hier sind ein paar link über die Verwendung von WinDbg für den Einbruch in verwaltetem code und eine Speicher-Adresse von einem JIT-ed-Methode. Ich glaube, dass Sie sollten in der Lage sein, einen Weg zu finden, um JIT-ed-code für eine Methode gibt es unter: Festlegen eines Haltepunkts in WinDbg für Verwalteten Code, SOS-Cheat-Sheet (.NET 2.0/3.0/3.5).
Können Sie auch versuchen, um ein Problem melden zu Microsoft. Wahrscheinlich ist dies eine CLR-debugger Fehler.
Danke für die interessante Frage.
Mit VS2010 SP1, es reagiert auf die Letzte Zeile, wenn Sie einen Haltepunkt in den release-Modus. Eigentlich sollte man es installieren, es wird insbesondere erwähnt, dass es debugger behebt Probleme, in denen es manchmal zu überspringen, breakpoints (obwohl nicht in diesem speziellen Fall).
Ändern Sie Ihre build-Konfiguration "Debug" statt "Release".
Den JIT-compiler verwendet-Optimierung Techniken, kann dies dazu führen,.
Einer solchen Optimierung ist die sogenannte Methode inlining, dass kann verantwortlich sein für dieses Verhalten.
Kann ich nicht genau sagen jetzt, weil ich bin mit einer anderen person den computer... aber Sie können testen, ob Sie sich selbst:
1) Erstellen Sie die folgende Methode:
2) ersetzen Sie die Aufrufe von "Konsole.WriteLine" nur mit "MyMethod"
3) Legen Sie den Haltepunkt, und versuchen Sie es.
4) Jetzt entfernen Sie die "MethodImpl" - Attribut aus der Methode "Meinemethode".
5) erneut Ausgeführt wird, wird mit dem Haltepunkt an der gleichen Stelle.
6) Wenn es hält, die im ersten Durchlauf, aber nicht in den zweiten Lauf... dann ist das der Grund.
Ich denke, wenn Sie debug release " - Modus Ihre Haltepunkte entsprechen möglicherweise nicht den tatsächlichen Zeilen in den code, weil der Maschinen-code kann optimiert wurden. Bei deinem code, den Sie eigentlich nichts zu tun, Teil von drucken, die mit "1" und dann "2" also es wäre sicher davon ausgehen, dass der compiler den code entfernen der die (b==false), da es nie erreicht werden.
Gebäude die Veröffentlichung unterlässt der Erstellung der debug-Symbole, die in sich selbst ist offensichtlich.
Sie können dies überschreiben, indem Sie auf die Eigenschaften Ihres Projektes. wählen Sie die Release-Konfiguration und klicken Sie auf "Erweitert" auf dem Build-tab. Setzen Sie den Debug-Info zu voll.