Partager via


_resetstkoflw

Est récupérée de dépassement de capacité de la pile.

Important

Cette API ne peut pas être utilisée dans les applications qui s'exécutent dans les fenêtres d'exécution.Pour plus d'informations, consultez Fonctions CRT non prises en charge avec /ZW.

int _resetstkoflw ( void );

Valeur de retour

Une valeur différente de zéro si la fonction réussit, zéro s'il échoue.

Notes

La fonction _resetstkoflw est récupérée à partir d'une condition de dépassement de capacité de la pile, en autorisant un programme à continuer au lieu d'échouer en provoquant une erreur d'exception irrécupérable.Si la fonction d' _resetstkoflw n'est pas appelée, aucune page de garde après la précédente exception.Lors du prochain dépassement de capacité de la pile, aucune exception n'est levée et le processus s'achève sans avertissement.

Si un thread dans une application provoque une exception d' EXCEPTION_STACK_OVERFLOW, le thread a permis sa pile dans un état endommagé.Ce contraste avec d'autres exceptions comme EXCEPTION_ACCESS_VIOLATION ou EXCEPTION_INT_DIVIDE_BY_ZERO, où la pile n'est pas endommagée.La pile a une valeur arbitrairement petite lorsque le programme est d'abord chargé.La pile se développe ensuite à la demande pour répondre aux besoins du thread.Il est implémenté en définissant une page avec accès de PAGE_GUARD à la fin de la pile actuelle.Pour plus d'informations, consultez l' Créer des pages de garde.

Lorsque le code fait pointer vers le pointeur de pile une adresse dans cette page, une exception se produit et le système effectue les trois opérations suivantes :

  • Supprime la protection de PAGE_GUARD sur la page de garde afin que le thread puisse les lire et écrire des données dans la mémoire.

  • Alloue une page de garde qui se trouve une page sous de dernière.

  • Repasse l'instruction qui a déclenché l'exception.

De cette manière, le système peut augmenter la taille de la pile du thread automatiquement.Chaque thread d'un processus a une taille de la pile maximale.La taille de la pile est définie au moment de la compilation par /STACK (Allocations de la pile), ou par l'instruction de STACKSIZE dans le fichier .def pour le projet.

Lorsque cette taille de la pile maximale est dépassée, le système effectue les trois opérations suivantes :

  • Supprime la protection de PAGE_GUARD sur la page de garde, comme décrit précédemment.

  • Essaie d'allouer une page de garde sous de dernière.Toutefois, cela échoue car la taille de la pile maximale a été dépassée.

  • Lève une exception afin que le thread soit la gestion du bloc d'exception.

Notez que, à ce stade, la pile n'a plus une page de garde.La prochaine fois que le programme élève la pile complètement à la fin, où il doit y avoir une page de garde, écrit de programme au delà de la fin de la pile et entraîne une violation d'accès.

Appelez _resetstkoflw pour restaurer la page de garde chaque fois que le redémarrage est effectuée après une exception de dépassement de capacité de la pile.Cette fonction peut être appelée à l'intérieur de le corps principal d'un bloc ou d'un extérieur de __except un bloc de __except .Toutefois, il existe quelques restrictions à lorsqu'il doit être utilisé._resetstkoflw ne doit jamais être appelé à partir de :

  • Une expression de filtre.

  • Une fonction de filtre.

  • Une fonction appelée par une fonction de filtre.

  • Un bloc de collecteur .

  • Un bloc d' __finally .

À ces points, la pile n'est pas toujours suffisamment déroulée.

Les exceptions de dépassement de capacité de la pile sont générées comme les exceptions structurées, pas exceptions C++, ce _resetstkoflw n'est pas utile dans un bloc ordinaire de collecteur car il n'intercepte pas d'exception de dépassement de capacité de la pile.Toutefois, si _set_se_translator est utilisé pour implémenter un traducteur structurée des exceptions qui lève des exceptions C++ (comme dans le deuxième exemple), une exception de dépassement de capacité de la pile a provoqué l'exception c++ qui peut être gérée par le bloc catch c++.

Il est déconseillé d'appeler _resetstkoflw dans le bloc catch c++ qui est atteint d'une exception levée par la fonction de transcodage structurée des exceptions.Dans ce cas, l'espace de pile n'est pas libéré et le pointeur de pile n'est pas réinitialisées jusqu'à ce que en dehors de le bloc catch, même si les destructeurs ont été appelés pour tous les objets destructibles avant le bloc catch.Cette fonction ne doit pas être appelée jusqu'à ce que l'espace de pile soit libéré et le pointeur de pile a été réinitialisé.Par conséquent, elle doit être appelée uniquement après quitter le bloc catch.À mesure que peu d'espace de pile en tant que possible doit être utilisé dans le bloc catch parce qu'un dépassement de capacité de la pile qui se produit dans le bloc catch qui lui-même tente de récupérer d'un dépassement de capacité de la pile précédent n'est pas réparable et peut entraîner l'arrêt du programme de répondre pendant que le dépassement de capacité dans le bloc catch lève une exception qu'elle-même est géré par le même bloc catch.

Certaines situations _resetstkoflw peut échouer même s'il est utilisé dans un emplacement approprié, comme dans un bloc de __except .Si, même après déroulement de la pile, il ne reste pas assez d'espace de pile autorisé à exécuter _resetstkoflw sans écrire dans la dernière page de la pile, _resetstkoflw ne réinitialise pas à l'état initial de la dernière page de la pile comme page de garde et retourne 0, indiquant l'échec.Par conséquent, l'utilisation sécurisée de cette fonction doit inclure vérifier la valeur de retour au lieu de supposer qu'il est sécurisée utiliser la pile.

La gestion structurée des exceptions n'intercepte pas d'exception STATUS_STACK_OVERFLOW lorsque l'application est compilée avec /clr ou /clr:pure (consultez /clr (Compilation pour le Common Language Runtime)).

Configuration requise

Routine

En-tête requis

_resetstkoflw

<malloc.h>

Pour plus d'informations de compatibilité, consultez Compatibilité dans l'introduction.

Bibliothèques : toutes les versions de Fonctionnalités de bibliothèque CRT.

Exemple

L'exemple suivant illustre l'utilisation recommandée de la fonction d' _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;
}

Résultat de l'exemple

Sans argument de programme :

loop #1

Le programme cesse de répondre sans exécuter d'autres itérations.

Avec les arguments de programme :

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

L'exemple suivant illustre l'utilisation recommandée pour _resetstkoflw dans un programme où les exceptions structurées sont converties en exceptions C++.

89f73td2.collapse_all(fr-fr,VS.110).gifCode

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

Résultat de l'exemple

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.

Équivalent .NET Framework

Non applicable. Pour appeler la fonction C standard, utilisez PInvoke. Pour plus d'informations, consultez l' Exemples d'appel de code non managé.

Voir aussi

Référence

_alloca