Partilhar via


_resetstkoflw

Recupera de estouro de pilha.

int _resetstkoflw ( void );

Valor de retorno

Diferente de zero se a função obtiver êxito, o zero se ele falhar.

Comentários

The _resetstkoflw função recupera de uma condição de estouro de pilha, permitindo que um programa continuar, em vez de apresentar um erro de exceção fatal. Se o _resetstkoflw função não é chamada, não há nenhuma página de proteção após a exceção anterior. Estouro na próxima vez que há uma pilha, não há nenhuma exceção em todos os e o processo é encerrado sem aviso.

Se um thread em um aplicativo faz com que um EXCEPTION_STACK_OVERFLOW exceção, o thread deixou sua pilha em um estado danificado.Isso é contrário para outras exceções, sistema autônomo EXCEPTION_ACCESS_VIOLATION or EXCEPTION_INT_DIVIDE_BY_ZERO, onde a pilha não está danificada.A pilha é conjunto com um valor arbitrariamente pequeno quando o programa for carregado pela primeira vez.A pilha cresce, em seguida, sob demanda para atender às necessidades do thread.Isso é implementado colocando uma página com acesso PAGE_GUARD no participante da pilha corrente.Para obter mais informações, consulte Criando páginas proteção.

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

  • Remove a proteção PAGE_GUARD na página protetor para que o thread pode ler e gravar dados na memória.

  • Aloca um novo proteção ou seja localizada uma página abaixo da última página.

  • Executa novamente a instrução que gerou a exceção.

Dessa forma, o sistema pode aumentar o dimensionar da pilha do segmento automaticamente.Cada thread em um processo tem um dimensionar de pilha máximo.O dimensionar da pilha é definido no time de compilar, a /STACK (alocações de pilha), ou com o STACKSIZE demonstrativo no arquivo .def para o projeto.

Quando esse dimensionar de pilha máximo for excedido, o sistema faz três coisas a seguintes:

  • Remove a proteção PAGE_GUARD na página protetor, conforme descrita anteriormente.

  • Tenta alocar uma nova página protetor abaixo do último.No entanto, isso falha porque o dimensionar máximo de pilha foi excedido.

  • Gera uma exceção para que o thread pode manipular no bloco de exceção.

Observe que, neste ponto, a pilha não tem uma página de proteção.Na próxima vez que o programa cresce a pilha até o participante, onde deve haver uma página de proteção, o programa grava além do participante da pilha e causa uma violação de acesso.

De telefonar**_resetstkoflw** restauração a página de proteção sempre que a recuperação é feita após uma exceção de estouro de pilha. Esta função pode ser chamada a partir de dentro do corpo principal de um __except bloco ou externa um __except bloco.No entanto, há algumas restrições sobre quando deve ser usado._resetstkoflw nunca deve ser chamado de:

  • Uma expressão de filtro.

  • Uma função de filtro.

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

  • A catch bloco.

  • A __finally bloco.

Nestes pontos, a pilha ainda não está suficientemente organizada.

Exceções de estouro de pilha são geradas sistema autônomo exceções estruturadas, não exceções do C++, então, _resetstkoflw não é útil em um comum catch bloco porque ele não irá capturar uma exceção de estouro de pilha.No entanto, se _set_se_translator é usado para implementar um conversor de exceção estruturada que lança exceções do C++ (sistema autônomo no segundo exemplo), uma exceção de estouro de pilha resultados em uma exceção de C++ que pode ser manipulada por um bloco catch do C++.

Não é seguro chamar _resetstkoflw em um C++ catch que é acessado de uma exceção lançada pela função tradutor de exceção estruturada.Nesse caso, o espaço de pilha não é liberado e o ponteiro de pilha não é reiniciar até fora do bloco catch, embora destruidores tem foi chamados para todos os objetos destructible antes do bloco catch.Esta função não deve ser chamada até que o espaço de pilha é liberado e o ponteiro de pilha foi redefinido.Portanto, deve ser chamado somente depois de sair do bloco catch.Espaço pilha apenas sistema autônomo possíveis devem ser usado no bloco catch, porque um estouro de pilha ocorre no bloco catch que é tentar fazer a recuperação a partir de um estouro de pilha anterior não é recuperável e pode causa o programa pare de responder enquanto o estouro no bloco catch aciona uma exceção que se é tratado pelo mesmo bloco catch.

Há situações em que _resetstkoflw pode falhar, mesmo se usada em um local correto, por exemplo, dentro um __except bloco.Se, mesmo depois desenrolar a pilha, ainda não há espaço de pilha suficiente para executar o _resetstkoflw sem escrever para a última página da pilha, _resetstkoflw não pode reiniciar a última página de pilha sistema autônomo a página de proteção e retorna 0, indicando falha.Portanto, uso seguro desta função deve incluir verificando o valor retornado em vez de supondo que a pilha é segurança.

Manipulação de exceção estruturada não irá capturar um STATUS_STACK_OVERFLOW exceção quando o aplicativo é compilado com /clr ou /clr:pure (consulte a o CLR (ComComummon Idioma Tempo de execução ComComumpilation)).

Requisitos

Rotina

Cabeçalho necessário

_resetstkoflw

<malloc.h>

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

Bibliotecas: Todas as versões do C em time de execução bibliotecas.

Exemplo

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

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

Saída de exemplo

Sem argumentos do programa:

loop #1

O programa pára de responder sem executar mais iterações.

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

Descrição

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

Có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;
}

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.

Equivalente do NET Framework

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

Consulte também

Referência

_alloca