Warum können unter 64-Bit-Windows Benutzer-Kernel-Benutzer-Ausnahmen nicht behoben werden?
Warum kann 64-Bit-Windows den Stapel während einer Ausnahme nicht auflösen, wenn der Stapel die Kernelgrenze überschreitet - wenn 32-Bit-Windows dies kann?
Der Kontext dieser gesamten Frage ergibt sich aus:
Der Fall der verschwindenden OnLoad-Ausnahme - Callback-Ausnahmen im Benutzermodus in x64
HintergrundIn 32-Bit-Windows, wenn ich eine Ausnahme in meinemBenutzermodus Code, der von zurückgerufen wurdeKernel-Modus Code, der von meinem aufgerufen wurdeBenutzermodus Code, z.B.
User mode Kernel Mode
------------------ -------------------
CreateWindow(...); ------> NtCreateWindow(...)
|
WindowProc <---------------------+
Die strukturierte Ausnahmebehandlung (Structured Exception Handling, SEH) in Windows kann den Stapel abwickeln, indem ich ihn im Kernelmodus in meinen Benutzercode zurückspule, wo ich die Ausnahme behandeln kann und eine gültige Stapelablaufverfolgung sehe.
Aber nicht in 64-Bit-Windows64-Bit-Editionen von Windows können dies nicht:
Aus komplizierten Gründen haben wirkann die Ausnahme nicht auf 64-Bit-Betriebssystemen weitergeben (amd64 und IA64). Dies ist seit der ersten 64-Bit-Version von Server 2003 der Fall. Bei x86 ist dies nicht der Fall - die Ausnahme wird über die Kernelgrenze verbreitet und wandert dann über die Frames zurück
Und da es in diesem Fall keine Möglichkeit gibt, einen zuverlässigen Stack-Trace zurückzuverfolgen, musste eine Entscheidung getroffen werden: Zeigen Sie die unsinnige Ausnahme an, oder verbergen Sie sie vollständig:
Die damaligen Kernel-Architekten entschieden sich für den konservativen AppCompat-freundlichen Ansatz - verstecken Sie die Ausnahme und hoffen Sie auf das Beste.
In diesem Artikel wird erläutert, wie sich alle 64-Bit-Windows-Betriebssysteme wie folgt verhalten haben:
Windows XP 64-BitWindows Server 2003 64-BitWindows Vista 64-BitWindows Server 2008 64-BitAber ab Windows 7 (und Windows Server 2008) haben die Architekten ihre Meinung geändert - irgendwie. Zumnur 64-Bit-Anwendungen (keine 32-Bit-Anwendungen), würden sie (standardmäßig)halt Unterdrücken dieser Benutzer-Kernel-Benutzer-Ausnahmen. Also standardmäßig auf:
Windows 7 64-BitWindows Server 2008Alle 64-Bit-Anwendungen werdensehen diese Ausnahmen, wo sie sie nie zu sehen pflegten.
In Windows 7, wenn anative x64 Anwendung stürzt auf diese Weise ab, dieProgrammkompatibilitäts-Assistent wird benachrichtigt. Wenn die Anwendung keinWindows 7-ManifestWir zeigen einen Dialog, der Ihnen mitteilt, dass PCA eineAnwendungskompatibilität shim. Was bedeutet das? Dies bedeutet, dass Windows beim nächsten Ausführen Ihrer Anwendung das Verhalten von Server 2003 emuliert und die Ausnahme verschwinden lässt. Bedenken Sie, dass PCA auf Server 2008 R2 nicht vorhanden ist, sodass dieser Hinweis nicht gilt.
Also die FrageDie Frage istWarum Ist 64-Bit-Windows nicht in der Lage, einen Stapel über einen Kernelübergang zurückzuspulen?können 32-Bit-Editionen von Windows?
Der einzige Hinweis ist:
Aus komplizierten Gründen haben wirkann die Ausnahme nicht auf 64-Bit-Betriebssystemen weitergeben (amd64 und IA64).
Der Hinweis istes ist kompliziert.
Ich verstehe die Erklärung vielleicht nicht, da ich kein Betriebssystementwickler bin - aber ich möchte gerne wissen, warum.
Update: Hotfix zum Beenden der Unterdrückung von 32-Bit-AppsMicrosoft hat freigegebena Hotfix ermöglicht 32-Bit-Anwendungen um auch die Ausnahmen nicht mehr zu unterdrücken:
KB976038: Ausnahmen, die von einer Anwendung ausgelöst werden, die in einer 64-Bit-Version von Windows ausgeführt wird, werden ignoriertEine Ausnahme, die in einer Rückrufroutine ausgelöst wird, wird im Benutzermodus ausgeführt.In diesem Szenario führt diese Ausnahme nicht zum Absturz der Anwendung. Stattdessen tritt die Anwendung in einen inkonsistenten Zustand ein. Dann löst die Anwendung eine andere Ausnahme aus und stürzt ab.
Eine Benutzermodus-Rückruffunktion ist normalerweise eine anwendungsdefinierte Funktion, die von einer Kernelmodus-Komponente aufgerufen wird. Beispiele für Rückruffunktionen im Benutzermodus sind Windows-Prozeduren und Hook-Prozeduren. Diese Funktionen werden von Windows aufgerufen, um Windows-Nachrichten oder Windows-Hook-Ereignisse zu verarbeiten.
Mit dem Hotfix können Sie dann verhindern, dass Windows die Ausnahmen global aufnimmt:
HKLM\SOFTWARE\Microsoft\Windows NT\CurrentVersion\Image File Execution Options
DisableUserModeCallbackFilter: DWORD = 1
oder pro Anwendung:
HKLM\SOFTWARE\Microsoft\Windows NT\CurrentVersion\Image File Execution Options\Notepad.exe
DisableUserModeCallbackFilter: DWORD = 1
Das Verhalten wurde auch unter XP und Server 2003 in KB973460 dokumentiert:
Ausnahmen, die von einer 64-Bit-Anwendung ausgelöst werden, die in den 64-Bit-Editionen von Windows Server 2003 oder Windows XP Professional ausgeführt wird, werden unbemerkt ignoriertEin HinweisIch habe einen weiteren Hinweis gefunden, als ich die Verwendung von Xperf zum Erfassen von Stack-Traces unter 64-Bit-Windows untersuchte:
Stack Walking in XperfPaging Executive deaktivieren
Damit die Ablaufverfolgung unter 64-Bit-Windows funktioniert, müssen Sie das Symbol festlegenDisablePagingExecutive Registrierungsschlüssel. Dadurch wird das Betriebssystem angewiesen, Kernelmodustreiber und Systemcode nicht auf die Festplatte zu übertragen. Dies ist eine Voraussetzung dafür, dass 64-Bit-Aufrufstapel mithilfe von xperf abgerufen werden können, da das Gehen von 64-Bit-Stapeln von Metadaten in den ausführbaren Abbildern abhängt xperfDer Stack-Walk-Code darf ausgelagerte Seiten nicht berühren. Wenn Sie den folgenden Befehl an einer Eingabeaufforderung mit erhöhten Rechten ausführen, wird dieser Registrierungsschlüssel für Sie festgelegt.
REG ADD "HKLM\System\CurrentControlSet\Control\Session Manager\Memory Management" -v
DisablePagingExecutive -d 0x1 -t REG_DWORD -f
Nach dem Festlegen dieses Registrierungsschlüssels müssen Sie Ihr System neu starten, bevor Sie Anrufstapel aufzeichnen können. Das Setzen dieses Flags bedeutet, dass der Windows-Kernel mehr Seiten in den Arbeitsspeicher sperrt, sodass dieser wahrscheinlich etwa 10 MB zusätzlichen physischen Arbeitsspeicher beansprucht.
Dies erweckt den Eindruck, dass Sie unter 64-Bit-Windows (und nur unter 64-Bit-Windows) keine Kernel-Stacks ausführen dürfen, da sich möglicherweise Seiten auf der Festplatte befinden.