Sdílet prostřednictvím


_resetstkoflw

Obnoví z přetečení zásobníku.

Důležitá poznámkaDůležité

Toto rozhraní API nelze použít v aplikacích, které jsou spuštěny v systému Windows Runtime.Další informace naleznete v tématu CRT funkce nejsou podporovány s /ZW.

int _resetstkoflw ( void );

Vrácená hodnota

Nenulová, je-li funkce úspěšná, nula, pokud se nezdaří.

Poznámky

_resetstkoflw Funkce obnoví ze stavu přetečení zásobníku, povolení programu pokračovat místo došlo k selhání s Závažná výjimka chyba.Pokud _resetstkoflw není volána funkce, nejsou žádné stránky guard po předchozí výjimky.Při příštím se zásobníku přetečení, nejsou vůbec žádné výjimky a ukončí proces bez předchozího upozornění.

V případě, že způsobí, že podproces v aplikaci EXCEPTION_STACK_OVERFLOW výjimka, vlákno opustil svůj zásobník poškozeného státu.Tím se liší od další výjimky, jako například EXCEPTION_ACCESS_VIOLATION nebo EXCEPTION_INT_DIVIDE_BY_ZERO, kde není poškozen zásobník.Zásobník je nastavena na libovolně malou hodnotu, při prvním načtení programu.Zásobník pak roste na požádání potřebám vlákna.To je implementována umístěním stránky s PAGE_GUARD přístup na konci aktuálního zásobníku.Další informace naleznete v tématu Vytváření stránek Guard.

Pokud kód způsobí, že ukazatel na zásobník tak, aby odkazovaly na adresu na této stránce, dojde k výjimce a systém provede následující tři věci:

  • Odebere ochranu PAGE_GUARD na ochranná stránka tak, aby bylo vlákno může číst a zapisovat data do paměti.

  • Alokuje novou guard stránky je umístěn jeden pod poslední.

  • Znovu spustí operaci, která vyvolala výjimku.

Tímto způsobem systém může zvětšit velikost zásobníku pro vlákno automaticky.Všechny vlákna v procesu má maximální velikost zásobníku.Velikost zásobníku je nastavena v čase kompilace pomocí / ZÁSOBNÍKU (zásobník rozdělení), nebo STACKSIZE příkaz v souboru .def pro projekt.

Při překročení této maximální velikost zásobníku, systém provede následující tři věci:

  • Odstraní ochranu PAGE_GUARD na stránce guard podle výše uvedených pokynů.

  • Systém se pokusí přidělení nové stránky guard pod poslední.To však nezdaří, protože byla překročena maximální velikost zásobníku.

  • Vyvolá výjimku, tak, aby bylo vlákno může zpracovávat v bloku výjimky.

Všimněte si, že v daném okamžiku zásobníku již má ochranná stránka.Dalším, že program roste až do konce zásobníku v případě, že by měla být ochranná stránka, program zapíše po skončení zásobníku a způsobuje chybu narušení přístupu.

Volání _resetstkoflw Chcete-li obnovit ochranná stránka při každém obnovení se provádí po výjimka přetečení zásobníku.Tuto funkci lze volat z hlavní části __except bloku nebo vnější __except bloku.Existují však některá omezení při by mělo být používáno._resetstkoflwby měl být nikdy volán z:

  • Výraz filtru.

  • Funkce filter.

  • Funkce je volána z funkce filter.

  • A catch bloku.

  • A __finally block.

V těchto místech zásobníku ještě není dostatečně pokračuj.

Výjimky přetečení zásobníku jsou generovány jako strukturované výjimky nejsou výjimky C++ tak, aby _resetstkoflw hodí není běžný catch blokovat, protože nebude zachytit výjimky přetečení zásobníku.Nicméně pokud _set_se_translator je používána k implementaci strukturované výjimky překladač, který vyvolá C++ výjimky (viz druhý příklad), výsledkem výjimka přetečení zásobníku výjimek v C++, která může být zpracována v bloku catch C++.

Není bezpečné volat _resetstkoflw v bloku catch C++, který je dosaženo z výjimku vyvolanou překladač funkce strukturované výjimky.V tomto případě není uvolněn prostor v zásobníku a ukazatel na zásobník není vynulován dokud mimo blok catch, přestože destruktory zavolání pro všechny zničitelné objekty před blok catch.Tato funkce by neměl volat, až uvolnění prostoru v zásobníku a ukazatel na zásobník byl resetován.Proto by měla být volána pouze po ukončení bloku catch.Co trochu místa v zásobníku a možná by měla sloužit blok catch, protože přetečení zásobníku, ke kterému dochází v bloku catch, který je sám pokus o obnovení z předchozí přetečení zásobníku je možné příčiny, které program přestane reagovat při přetečení v bloku catch vyvolá výjimku, která sama má na starosti stejné catch blokem.

Existují situace, kde _resetstkoflw může selhat, i v případě, že použití správné místo, například v rámci __except bloku.Je-li i po unwind zásobníku, je stále není dostatek místa v zásobníku vlevo k provedení _resetstkoflw bez psaní do poslední stránky zásobníku, _resetstkoflw se nepodařilo obnovit poslední stránku zásobníku jako ochranná stránka a vrátí hodnotu 0, označující selhání.Proto bezpečné používání této funkce by měl zahrnovat kontrolu vrácenou hodnotu, za předpokladu, že zásobník je bezpečně používat.

Strukturované zpracování výjimek nezachytí STATUS_STACK_OVERFLOW výjimka v případě, že aplikace je kompilována s /clr nebo /clr:pure (viz /CLR (kompilace společné Language Runtime)).

Požadavky

Byla zahájena rutina

Požadované záhlaví

_resetstkoflw

<malloc.h>

Další informace o kompatibilitě v tématu Kompatibilita v úvodu.

Knihovny: všech verzí Funkce knihovny CRT.

Příklad

Následující příklad ukazuje doporučené použití _resetstkoflw funkce.

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

Vzorový výstup

Bez argumentů programu:

loop #1

Aplikace přestane reagovat bez dalšího spuštění iterací.

Pomocí programu argumenty:

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(cs-cz,VS.110).gifDescription

Následující příklad ukazuje doporučené použití _resetstkoflw v programu, kde jsou strukturované výjimky převedeny na výjimky C++.

89f73td2.collapse_all(cs-cz,VS.110).gifKód

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

Vzorový výstup

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.

Ekvivalent v rozhraní .NET Framework

Nelze použít Volání funkce standardním C pomocí PInvoke. Další informace naleznete v tématu Platformu vyvolání příklady.

Viz také

Referenční dokumentace

_alloca