Udostępnij za pośrednictwem


_resetstkoflw

Odzyskuje z przepełnieniem stosu.

Ważna uwagaWażne

Ten interfejs API nie można używać w aplikacji, których wykonywanie w czasie wykonywania systemu Windows.Aby uzyskać więcej informacji, zobacz CRT funkcje nie obsługiwane przez /ZW.

int _resetstkoflw ( void );

Wartość zwracana

Różna od zera, jeśli funkcja się powiedzie, zero w przypadku awarii.

Uwagi

Funkcja _resetstkoflw powraca ze stanu przepełnienia stosu, pozwalając programowi na kontynuowanie zamiast zakończenia pracy zwracając błąd wyjątku krytycznego.Jeśli _resetstkoflw funkcja nie jest wywoływana, Brak stron guard po poprzedniego wyjątku.Przy następnym przepełnieniu stosu nie wystąpią żadne wyjątki a proces zakończy się bez ostrzeżenia.

Jeśli wątek w aplikacji powoduje, że EXCEPTION_STACK_OVERFLOW wyjątku, wątek opuścił ze swojego stosu w Państwie uszkodzonych.To rożni się inne wyjątki takie jak EXCEPTION_ACCESS_VIOLATION lub EXCEPTION_INT_DIVIDE_BY_ZERO, gdzie stos nie jest uszkodzony.Stos jest równa arbitralnie małej wartości, przy pierwszym uruchomieniu programu.Stos następnie zwiększa się na żądanie, aby zaspokoić potrzeby wątku.To jest zaimplementowany przez umieszczenie strony z dostępem PAGE_GUARD na koniec bieżącego stosu.Aby uzyskać więcej informacji, zobacz Tworzenie stron Guard.

Gdy kod powoduje, że wskaźnik stosu wskazywały na adres na tej stronie, wystąpi wyjątek i system wykonuje następujących czynności:

  • Usuwa ochrony PAGE_GUARD, na stronie guard, tak aby wątek można odczytywać i zapisywać dane do pamięci.

  • Przydziela nową osłonę strony oznacza to się jedną stronę pod ostatnią.

  • Umożliwia ponowne wykonanie instrukcji, która wzbudziła wyjątek.

Dzięki temu system może automatycznie zwiększyć rozmiar stosu wątku.Każdy wątek w procesie ma rozmiar maksymalny stosu.Rozmiar stosu jest ustawiany w czasie kompilacji przez / STACK (stos alokacje), lub przez STACKSIZE w pliku .def dla projektu.

Gdy zostanie przekroczony ten rozmiar maksymalny stosu, system wykonuje następujących czynności:

  • Usuwa ochrony PAGE_GUARD, na stronie guard, w sposób opisany wcześniej.

  • Próbuje przydzielić nowej strony strażnika poniżej ostatnia z nich.Jednak to się nie powiedzie, ponieważ przekroczono rozmiar maksymalny stosu.

  • Zgłasza wyjątek, tak aby wątek może je obsłużyć w bloku wyjątków.

Należy zauważyć, że w tym momencie, stosu nie ma już strona ochronna.Następnym razem, że rośnie stosie aż do końca, w przypadku, gdy powinno być strony ochronnej, program pisze poza koniec stosu i powoduje naruszenie zasad dostępu.

Call _resetstkoflw do przywrócenia Strona ochronna w każdym przypadku, gdy odzyskiwania można to zrobić po wyjątku przepełnienia stosu.Ta funkcja może być wywołana z wewnątrz głównej części __except bloku czy poza __except bloku.Istnieją jednak pewne ograniczenia na kiedy powinny być używane._resetstkoflwnigdy nie powinna zostać wywołana z:

  • Wyrażenie filtru.

  • Funkcja filtru.

  • Funkcja o nazwie przez funkcję filtru.

  • A połowu bloku.

  • A __finally block.

W tych punktach stos nie jest jeszcze wystarczająco zlikwidowany.

Wyjątki przepełnienie stosu są generowane jako wyjątki strukturalne, nie wyjątki C++, tak _resetstkoflw nie jest przydatne w zwykłym połowu blok, ponieważ nie będzie przechwytywać wyjątku przepełnienia stosu.Jednakże jeśli _set_se_translator jest używane do implementowania translatora strukturalnej wyjątków, który generuje wyjątki C++ (jak w drugim przykładzie), powoduje wyjątek przepełnienia stosu wyjątków C++, które mogą być obsługiwane przez blok catch języka C++.

To nie może wywołać _resetstkoflw w bloku catch języka C++, otwieranym z wyjątek funkcja Tłumacz structured exception.W takim przypadku miejsce stos nie jest zwalniane, a wskaźnik stosu nie jest resetowany, dopóki poza blok catch, mimo że destruktory została wywołana dla dowolnego uderzeniową przed blok catch.Ta funkcja nie powinna być wywoływana, dopóki nie jest zwalniany przestrzeni stosu, a wskaźnik stosu została zresetowana.W związku z tym powinna zostać wywołana tylko po wyjściu z bloku catch.Jak najmniej pamięci stosu, jak to możliwe, należy używać w bloku catch, ponieważ przepełnienie stosu, który występuje w bloku catch, która sama próby odzyskania z poprzedniego przepełnienie stosu jest jest nie do odzyskania i może przyczyną od program przestanie odpowiadać, jak przepełnienie w bloku catch powoduje wyjątek, który sam jest obsługiwany przez ten sam blok catch.

Istnieją sytuacje, gdzie _resetstkoflw może się nie powieść, nawet jeśli używane w właściwej lokalizacji, na przykład w ramach __except bloku.Jeśli, nawet po odkręcaniu stosu, nadal nie ma wystarczająco duży obszar stosu pozostało do wykonania _resetstkoflw bez pisania na ostatniej stronie stosu, _resetstkoflw nie powiedzie się przywrócić na ostatniej stronie stosu jako strona ochronna i zwraca wartość 0, wskazując niepowodzenie.W związku z tym bezpiecznego korzystania z tej funkcji powinien obejmować sprawdzenie wartości zwracanej, a nie, przy założeniu, że stosu jest bezpieczne w użyciu.

Strukturalną obsługę wyjątków nie będzie przechwytywać STATUS_STACK_OVERFLOW wyjątek podczas kompilowania aplikacji z /clr lub /clr:pure (zobacz / CLR (kompilacja wspólnej Language Runtime)).

Wymagania

Rozpoczęto wykonywanie procedury

Wymaganego nagłówka

_resetstkoflw

<malloc.h>

Informacji dotyczących zgodności, zobacz Zgodność we wprowadzeniu.

Biblioteki: wszystkie wersje programu Funkcje biblioteki CRT.

Przykład

W poniższym przykładzie pokazano sposób użycia z _resetstkoflw funkcji.

// 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;
}

Przykładowe dane wyjściowe

Bez argumentów program:

loop #1

Program nie odpowiada bez dalszego wykonywania iteracji.

Z argumentami program:

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

89f73td2.collapse_all(pl-pl,VS.110).gifOpis

W poniższym przykładzie pokazano zalecane używanie _resetstkoflw w programie, w których wyjątki strukturalne są konwertowane na wyjątki C++.

89f73td2.collapse_all(pl-pl,VS.110).gifKod

// 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;
}

Przykładowe dane wyjściowe

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.

Odpowiednik w programie .NET Framework

Nie dotyczy. Aby wywoływać funkcji C standardowej, należy użyć PInvoke. Aby uzyskać więcej informacji, zobacz Przykłady wywołać platformy.

Zobacz też

Informacje

_alloca