Partilhar via


resetstkoflw

Recupera de estouro de pilha.

Observação importanteImportante

Este API não pode ser usado em aplicativos executados em Tempo de Execução do Windows.Para obter mais informações, consulte Funções de CRT não suportadas com /ZW.

int _resetstkoflw ( void );

Valor de retorno

Diferente de zero se a função é bem-sucedido, zero se falhar.

Comentários

A função de _resetstkoflw recupera de uma condição de estouro de pilha, permitindo que um programa continua em vez de falhar com um erro fatal de exceção.Se a função de _resetstkoflw não é chamada, não há nenhuma página da barreira depois da exceção anterior.Na próxima vez que há um estouro de pilha, não há nenhuma exceção de todo e o processo termina sem aviso.

Se um segmento em um aplicativo causa uma exceção de EXCEPTION_STACK_OVERFLOW , o segmento deixa a pilha em um estado corrompido.Isso está em contraste com outras exceções como EXCEPTION_ACCESS_VIOLATION ou EXCEPTION_INT_DIVIDE_BY_ZERO, onde a pilha não estiver corrompida.A pilha é definida como um valor arbitrariamente pequeno quando o programa é carregada pela primeira vez.A pilha aumenta em sob demanda para atender às necessidades de segmento.Isso é implementado colocando uma página com acesso de PAGE_GUARD no final da pilha atual.Para obter mais informações, consulte Criando páginas de objeto.

Quando o código faz com que o ponteiro de pilha para apontar para um endereço nessa página, uma exceção ocorre e o sistema faz as três coisas:

  • Remove a proteção de PAGE_GUARD na página de proteção para que o segmento possa ler e gravar dados na memória.

  • Atribui uma página do novo objeto que é encontrada uma página abaixo da última.

  • Executa novamente a instrução que lançou a exceção.

Dessa forma, o sistema pode aumentar o tamanho da pilha para o segmento automaticamente.Cada segmento em um processo tem um tamanho máximo de pilha.O tamanho da pilha é definido em tempo de compilação por / PILHA (alocações de pilha), ou pela instrução de STACKSIZE no arquivo de .def para o projeto.

Quando esse tamanho máximo de pilha é excedido, o sistema faz as três coisas:

  • Remove a proteção de PAGE_GUARD na página do objeto, como descrito anteriormente.

  • Tenta atribuir uma nova página de backup abaixo da última.No entanto, isso falha porque o tamanho máximo de pilha foi excedido.

  • Gera uma exceção de modo que o segmento possa tratá-lo no bloco de exceção.

Observe que, nesse ponto, a pilha ainda não tiver uma página de backup.Na próxima vez que o programa aumenta a pilha qualquer forma ao final, onde deve haver uma página da barreira, grava o programa além do final da pilha e uma causa uma violação de acesso.

Chame _resetstkoflw para restaurar a página de backup sempre que a recuperação é feita após uma exceção de estouro de pilha.Essa função pode ser chamada de dentro do corpo principal de um bloco ou de uma classe fora de __except um bloco de __except .No entanto, há algumas restrições sobre quando ele deve ser usado._resetstkoflw nunca deve ser chamado de:

  • Uma expressão de filtro.

  • Uma função de filtro.

  • Uma função chamada de uma função de filtro.

  • Um bloco catch de.

  • Um bloco de __finally .

Nesses pontos, a pilha desenrolada ainda não é suficientemente.

As exceções de estouro de pilha são geradas como as exceções estruturado de exceções, não C++, portanto _resetstkoflw não são úteis em comum de um bloco catch porque não irá capturar uma exceção de estouro de pilha.No entanto, se set_se_translator é usado para implementar um tradutor de exceção estruturada que lança exceções C++ (como o segundo exemplo), uma exceção de estouro de pilha resulta na exceção de c++ que pode ser tratado pelo bloco catch de c++.

Não é seguro chamar _resetstkoflw no bloco catch de c++ que é alcançado de uma exceção acionada pela função de tradutor de exceção estruturada.Nesse caso, o espaço de pilha não é lançado e o ponteiro de pilha não foi redefinido até que fora do bloco catch, mesmo que os destruidores serem chamados para todos os objetos destrutíveis antes que o bloco catch.Essa função não deve ser chamada até que o espaço de pilha será liberado e o ponteiro de pilha é redefinido.Como consequência, deve ser chamado somente após sair do bloco catch.Tão vez espaço de pilha como possível deve ser usado no bloco catch como um estouro de pilha que ocorra no bloco catch que próprio está tentando recuperar o de um estouro de pilha anterior é não recuperável e pode fazer com que o programa pára de responder como overflow no bloco catch aciona uma exceção que ela será manipulado pelo mesmo bloco catch.

Há situações onde _resetstkoflw pode falhar se usado em um local correto, como em um bloco de __except .Se, mesmo após o desenrolamento de pilha, ainda não há espaço suficiente de pilha para executar _resetstkoflw deixado sem escrever na última página de pilha, _resetstkoflw não redefine a última página de pilha porque a página do objeto e retorna 0, indicando a falha.Como consequência, o uso de segurança da função deve incluir verificar o valor de retorno em vez de presuma que a pilha é segura de usar.

Manipulação estruturada de exceções não irá capturar uma exceção de STATUS_STACK_OVERFLOW quando o aplicativo é compilado com /clr ou /clr:pure (consulte /CLR (common Language Runtime Compilation)).

Requisitos

Rotina

Cabeçalho necessário

_resetstkoflw

<malloc.h>

Para mais informações, consulte Compatibilidade de compatibilidade na introdução.

Bibliotecas: todas as versões de Recursos da biblioteca CRT.

Exemplo

O exemplo a seguir mostra o uso recomendado de função de _resetstkoflw .

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

A saída de exemplo

Sem argumentos do programa:

loop #1

O programa para responder sem executar uma de iterações adicionais.

Com argumentos do programa:

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(pt-br,VS.110).gifDescrição

O exemplo a seguir mostra o uso recomendado de _resetstkoflw em um programa onde as exceções estruturado de exceções são convertidas em C++.

89f73td2.collapse_all(pt-br,VS.110).gifCódigo

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

A saída de exemplo

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.

Equivalência do .NET Framework

Não aplicável. Para chamar a função padrão de C, use PInvoke. Para obter mais informações, consulte Exemplos de invocação de plataforma.

Consulte também

Referência

_alloca