_resetstkoflw
Erholt sich von Stapelüberlauf.
Wichtig |
---|
Diese API kann nicht in den Anwendungen verwendet werden, die in der Windows Runtime ausführen.Weitere Informationen finden Sie unter CRT-Funktionen unterstützt nicht mit /ZW. |
int _resetstkoflw ( void );
Rückgabewert
ungleich 0 (null), wenn die Funktion folgt, gleich, wenn fehlschlägt.
Hinweise
Die _resetstkoflw-Funktion sorgt nach Stapelüberläufen für eine Wiederherstellung, sodass ein Programm fortgesetzt werden kann, statt mit einem schwerwiegenden Ausnahmefehler fehlzuschlagen.Wenn die _resetstkoflw-Funktion nicht aufgerufen wird, gibt es keine Absicherungsseiten nach der vorherigen Ausnahme.Beim nächsten Stapelüberlauf treten keine Ausnahmen auf, und der Prozess wird ohne Ausgabe einer Warnung beendet.
Wenn ein Thread in einer Anwendung eine EXCEPTION_STACK_OVERFLOW Ausnahme verursacht, verfügt der Thread dessen Stapel in einem beschädigten Zustand belassen.Dies steht im Gegensatz zu anderen Ausnahmen wie EXCEPTION_ACCESS_VIOLATION oder EXCEPTION_INT_DIVIDE_BY_ZERO, in dem der Stapel nicht beschädigt wird.Der Stapel wird einem beliebig klein Wert festgelegt, wenn das Programm zuerst geladen wird.Der Stapel nimmt dann bei Bedarf, um die Anforderungen des Threads zu erfüllen.Dies wird implementiert, indem eine Seite mit PAGE_GUARD-Zugriff am Ende des aktuellen Stapels platziert.Weitere Informationen finden Sie unter Erstellen von Absicherungsseiten.
Wenn der Code den Stapelzeiger bewirkt, dass auf eine Adresse auf dieser Seite zu zeigen, wird eine Ausnahme ausgelöst und das System werden von die folgenden drei Dinge:
Entfernt den PAGE_GUARD-Schutz auf der Absicherungsseite, sodass der Thread Daten im Speicher lesen und schreiben kann.
Ordnet eine neue Absicherungsseite zu, der eine Seite aus dem letzten befindet.
Wiederholt die Anweisung, die die Ausnahme ausgelöst hat.
Auf diese Weise kann das System die Größe des Stapels für den Thread automatisch erhöhen.Jeder Thread in einem Prozess hat eine maximale Stapelgröße.Die Stapelgröße wird zur Kompilierungszeit durch /STACK (Stapelreservierungen) oder durch die STACKSIZE-Anweisung in der DEF-Datei für das Projekt festgelegt.
Wenn diese maximale Stapelgröße überschritten wird, erstellt das System die folgenden drei Dinge:
Entfernt den PAGE_GUARD-Schutz auf der Absicherungsseite, wie zuvor beschrieben.
Versucht, eine neue Absicherungsseite unter dem letzten zuzuordnen.Allerdings gilt dies aus, da die maximale Stapelgröße überschritten wurde.
Löst eine Ausnahme aus, damit der Thread diese im Ausnahmeblock behandeln kann.
Beachten Sie, dass an diesem Punkt der Stapel nicht mehr eine Absicherungsseite verfügt.Beim nächsten Ausführen das das Programm den Stapel alle auf das Ende vergrößert, in dem es eine Absicherungsseite geben sollte, schreibt das Programm über das Ende des Stapels hinaus und eine Zugriffsverletzung.
Rufen Sie _resetstkoflw auf, um die Absicherungsseite wiederherzustellen, wenn Wiederherstellung nach einer Stapelüberlaufausnahme erfolgt.Diese Funktion kann aus dem Hauptteil eines __except-Blocks oder -außenseite ein __except -Block heraus aufgerufen werden.Es gibt jedoch einige Einschränkungen auf, wenn verwendet werden soll._resetstkoflw sollte nie von aufgerufen werden:
Ein Filterausdruck.
Eine Filterfunktion.
Eine Funktion aufgerufen aus einer Filterfunktion.
Ein catch-Block.
Ein __finally-Block.
Zu diesen Punkten wird der Stapel noch nicht ausreichend.
Ausnahmen für Stapelüberläufe werden generiert, da strukturierte Ausnahmen, nicht C++-Ausnahmen, sodass _resetstkoflw nicht in einem normalen catch-Block hilfreich, da er nicht Stapelüberlaufausnahme abfängt.Wenn _set_se_translator verwendet wird, um einen Übersetzer der strukturierten Ausnahme zu implementieren, der C++-Ausnahmen (wie im zweiten Beispiel) ausgelöst wird, führt eine Stapelüberlaufausnahme eine C++-Ausnahme, die von einer C++-Datei catch-Block behandelt werden kann.
Es ist nicht sicher, _resetstkoflw catch-Block in einer C++-Datei aufzurufen, der von einer Ausnahme erreicht wird, die von der Übersetzerfunktion der strukturierten Ausnahme ausgelöst wird.In diesem Fall wird der Stapelspeicher nicht freigegeben und der Stapelzeiger wird erst außerhalb der catch-Block zurückgesetzt, obwohl Destruktoren für alle zerstörbaren Objekte vor dem catch-Block aufgerufen wurden.Diese Funktion sollte nicht aufgerufen werden, bis der Stapelspeicher freigegeben ist und der Stapelzeiger zurückgesetzt wurde.Daher sollte sie erst nach dem Beenden des catch-Blocks aufgerufen werden.Während wenig Stapelspeicherplatz benötigen als beliebiges im catch-Block verwendet werden soll, da ein Stapelüberlauf, der im catch-Block selbst auftritt, der versucht, sich von der vorherigen Stapelüberlauf zu beheben, nicht wiederherstellbar ist und das Programm bewirken kann nicht mehr reagiert, während der Überlauf im catch-Block eine Ausnahme auslöst, die selbst über denselben catch-Block behandelt wird.
Es gibt Situationen, in denen _resetstkoflw fehlschlagen kann, wenn in verwendet in einer korrekten Position, wie einem __except -Block.Wenn, nachdem, den Stapel beim Entladen, es noch nicht genügend Stapelspeicher gibt, der fehlgeschlagen ist, _resetstkoflw auszuführen, ohne zu schreiben in die letzte Seite des Stapels, kann _resetstkoflw die letzte Seite des Stapels als die Absicherungsseite zurücksetzen nicht und gibt 0 zurück und gibt Fehler an.Daher sollte sichere Verwendung dieser Funktion das Überprüfen des Rückgabewerts enthalten, anstatt, davon auszugehen, dass der Stapel sicher zu verwenden ist.
Strukturierte Ausnahmebehandlung fängt keine STATUS_STACK_OVERFLOW Ausnahme, wenn die Anwendung mit /clr oder /clr:pure kompiliert wird (siehe /clr (Common Language Runtime-Kompilierung)).
Anforderungen
Routine |
Erforderlicher Header |
---|---|
_resetstkoflw |
<malloc.h> |
Weitere Kompatibilitätsinformation finden Sie unter Kompatibilität in der Einführung.
Bibliotheken: alle Versionen CRT-Bibliotheks-Funktionen.
Beispiel
Das folgende Beispiel zeigt die empfohlene Verwendung der _resetstkoflw-Funktion an.
// crt_resetstkoflw.c
// Launch program with and without arguments to observe
// the difference made by calling _resetstkoflw.
#include <malloc.h>
#include <stdio.h>
#include <windows.h>
void recursive(int recurse)
{
_alloca(2000);
if (recurse)
recursive(recurse);
}
// Filter for the stack overflow exception.
// This function traps the stack overflow exception, but passes
// all other exceptions through.
int stack_overflow_exception_filter(int exception_code)
{
if (exception_code == EXCEPTION_STACK_OVERFLOW)
{
// Do not call _resetstkoflw here, because
// at this point, the stack is not yet unwound.
// Instead, signal that the handler (the __except block)
// is to be executed.
return EXCEPTION_EXECUTE_HANDLER;
}
else
return EXCEPTION_CONTINUE_SEARCH;
}
int main(int ac)
{
int i = 0;
int recurse = 1, result = 0;
for (i = 0 ; i < 10 ; i++)
{
printf("loop #%d\n", i + 1);
__try
{
recursive(recurse);
}
__except(stack_overflow_exception_filter(GetExceptionCode()))
{
// Here, it is safe to reset the stack.
if (ac >= 2)
{
puts("resetting stack overflow");
result = _resetstkoflw();
}
}
// Terminate if _resetstkoflw failed (returned 0)
if (!result)
return 3;
}
return 0;
}
Beispielausgabe
Ohne Programmargumente:
loop #1
Das Programm wird beendet, zu reagieren, ohne weitere Iterationen auszuführen.
Mit Programmargumenten:
loop #1
resetting stack overflow
loop #2
resetting stack overflow
loop #3
resetting stack overflow
loop #4
resetting stack overflow
loop #5
resetting stack overflow
loop #6
resetting stack overflow
loop #7
resetting stack overflow
loop #8
resetting stack overflow
loop #9
resetting stack overflow
loop #10
resetting stack overflow
Beschreibung
Das folgende Beispiel zeigt die empfohlene Verwendung von _resetstkoflw in einem Programm, in dem strukturierte Ausnahmen zu C++-Ausnahmen konvertiert werden.
Code
// crt_resetstkoflw2.cpp
// compile with: /EHa
// _set_se_translator requires the use of /EHa
#include <malloc.h>
#include <stdio.h>
#include <windows.h>
#include <eh.h>
class Exception { };
class StackOverflowException : Exception { };
// Because the overflow is deliberate, disable the warning that
// this function will cause a stack overflow.
#pragma warning (disable: 4717)
void CauseStackOverflow (int i)
{
// Overflow the stack by allocating a large stack-based array
// in a recursive function.
int a[10000];
printf("%d ", i);
CauseStackOverflow (i + 1);
}
void __cdecl SEHTranslator (unsigned int code, _EXCEPTION_POINTERS*)
{
// For stack overflow exceptions, throw our own C++
// exception object.
// For all other exceptions, throw a generic exception object.
// Use minimal stack space in this function.
// Do not call _resetstkoflw in this function.
if (code == EXCEPTION_STACK_OVERFLOW)
throw StackOverflowException ( );
else
throw Exception( );
}
int main ( )
{
bool stack_reset = false;
bool result = false;
// Set up a function to handle all structured exceptions,
// including stack overflow exceptions.
_set_se_translator (SEHTranslator);
try
{
CauseStackOverflow (0);
}
catch (StackOverflowException except)
{
// Use minimal stack space here.
// Do not call _resetstkoflw here.
printf("\nStack overflow!\n");
stack_reset = true;
}
catch (Exception except)
{
// Do not call _resetstkoflw here.
printf("\nUnknown Exception!\n");
}
if (stack_reset)
{
result = _resetstkoflw();
// If stack reset failed, terminate the application.
if (result == 0)
exit(1);
}
void* pv = _alloca(100000);
printf("Recovered from stack overflow and allocated 100,000 bytes"
" using _alloca.");
return 0;
}
Beispielausgabe
0 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24
Stack overflow!
Recovered from stack overflow and allocated 100,000 bytes using _alloca.
.NET Framework-Entsprechung
Nicht zutreffend. Um die Standard-C-Funktion aufzurufen, verwenden Sie PInvoke. Weitere Informationen finden Sie unter Beispiele für Plattformaufrufe.