Aracılığıyla paylaş


_resetstkoflw

Yığın taşmasından kurtarır.

Önemli

Bu API, Windows Çalışma Zamanı yürütülen uygulamalarda kullanılamaz. Daha fazla bilgi için bkz. Evrensel Windows Platformu uygulamalarında desteklenmeyen CRT işlevleri.

Sözdizimi

int _resetstkoflw( void );

Dönüş değeri

İşlev başarılı olursa sıfır olmayan, başarısız olursa sıfır.

Açıklamalar

İşlev _resetstkoflw bir yığın taşması koşulundan kurtarılır ve önemli bir özel durum hatasıyla başarısız olmak yerine programın devam etmesi sağlanır. _resetstkoflw İşlev çağrılmazsa, önceki özel durumdan sonra koruma sayfası yoktur. Bir sonraki yığın taşmasında özel durum yoktur ve işlem uyarı olmadan sonlandırılır.

Bir uygulamadaki bir iş parçacığı özel EXCEPTION_STACK_OVERFLOW duruma neden olursa, iş parçacığı yığınını hasarlı durumda bırakmıştır. Bu özel durum, yığının zarar görmedikleri veya EXCEPTION_INT_DIVIDE_BY_ZEROgibi EXCEPTION_ACCESS_VIOLATION diğer özel durumlardan farklıdır. Program ilk yüklendiğinde yığın rastgele küçük bir değere ayarlanır. Ardından yığın, iş parçacığının gereksinimlerini karşılamak için isteğe bağlı olarak büyür. İsteğe bağlı büyüme, geçerli yığının sonuna erişimi olan PAGE_GUARD bir sayfa yerleştirilerek uygulanır. Daha fazla bilgi için bkz . Koruma sayfaları oluşturma.

Kod, yığın işaretçisinin bu sayfadaki bir adrese işaret etmesine neden olduğunda bir özel durum oluşur ve sistem aşağıdaki üç işlemi yapar:

  • İş parçacığının PAGE_GUARD belleğe veri okuyabilmesi ve yazabilmesi için koruma sayfasındaki korumayı kaldırır.

  • Son sayfanın altında bir sayfa bulunan yeni bir koruma sayfası ayırır.

  • Özel durumu tetikleyen yönergeyi yeniden çalıştırır.

Bu şekilde, sistem iş parçacığı için yığının boyutunu otomatik olarak artırabilir. Bir işlemdeki her iş parçacığının yığın boyutu üst sınırı vardır. Yığın boyutu derleme zamanında /STACK (Yığın Ayırmaları) seçeneğine veya projenin dosyasındaki .def deyimine göre STACKSIZE ayarlanır.

Bu en büyük yığın boyutu aşıldığında sistem aşağıdaki üç işlemi yapar:

  • Daha önce açıklandığı gibi koruma sayfasındaki PAGE_GUARD korumasını kaldırır.

  • Son sayfanın altında yeni bir koruma sayfası ayırmaya çalışır. Ancak, yığın boyutu üst sınırı aşıldığından ayırma başarısız olur.

  • İş parçacığının bunu özel durum bloğunda işleyebilmesi için bir özel durum oluşturur.

Bu noktada, yığının artık bir koruma sayfası yoktur. Program yığını, yığının sonundan sonra yazıldığı yere bir sonraki yetiştirişinde erişim ihlaline neden olur.

Yığın taşması özel durumu sonrasında kurtarma her yapıldığında koruma sayfasını geri yüklemek için çağırın _resetstkoflw . Bu işlev bir bloğun ana gövdesinden veya bir __except bloğun dışından __except çağrılabilir. Ancak, ne zaman kullanılması gerektiğine ilişkin bazı kısıtlamalar vardır. _resetstkoflw şu kaynaktan çağrılmamalıdır:

  • Filtre ifadesi.

  • Bir filtre işlevi.

  • Filtre işlevinden çağrılan bir işlev.

  • Bir catch blok.

  • Bir __finally blok.

Bu noktalarda yığın henüz yeterince kaldırılmamıştır.

Yığın taşması özel durumları, C++ özel durumları olarak değil yapılandırılmış özel durumlar olarak oluşturulur, bu nedenle _resetstkoflw yığın taşması özel durumunu yakalamayacağından sıradan catch bir blokta yararlı olmaz. Ancak, C++ özel durumları oluşturan yapılandırılmış bir özel durum çevirisi uygulamak için kullanılırsa _set_se_translator (ikinci örnekte olduğu gibi), bir yığın taşması özel durumu C++ catch bloğu tarafından işlenebilen bir C++ özel durumuyla sonuçlanır.

Yapılandırılmış özel durum çevirisi işlevi tarafından oluşan bir özel durumdan ulaşılan bir C++ catch bloğunda çağrı _resetstkoflw yapmak güvenli değildir. Bu durumda, yakalama bloğundan önce yok edilebilir nesneler için yıkıcılar çağrılmış olsa bile, yığın alanı serbest değildir ve yığın işaretçisi yakalama bloğunun dışına kadar sıfırlanmaz. Yığın alanı boşaltılana ve yığın işaretçisi sıfırlanana kadar bu işlev çağrılmamalıdır. Bu nedenle, yalnızca catch bloğundan çıktıktan sonra çağrılmalıdır. Yakalama bloğunda mümkün olduğunca az yığın alanı kullanılmalıdır. Önceki bir yığın taşmasından kurtarmaya çalışan catch bloğunda oluşan bir yığın taşması kurtarılamaz. Catch bloğundaki taşma, aynı catch bloğu tarafından işlenen bir özel durumu tetiklediğinden, programın yanıt vermeyi durdurmasına neden olabilir.

Blok içinde __except olduğu gibi doğru bir konumda kullanılıp kullanılmayabileceği durumlar _resetstkoflw vardır. Yığını geri aldıktan sonra bile yığının son sayfasına yazmadan yürütülecek _resetstkoflw yeterli yığın alanı kalmayabilir. Ardından, _resetstkoflw koruma sayfası olarak yığının son sayfasını sıfırlayamaz ve hata olduğunu belirten 0 değerini döndürür. Bu işlevin Kasa kullanımı, yığının kullanımı güvenli olduğunu varsaymak yerine dönüş değerini denetlemeyi içermelidir.

Yapılandırılmış özel durum işleme, uygulama ile derlendiğinde bir STATUS_STACK_OVERFLOW özel durum yakalamaz (bkz/clr. (Ortak Dil Çalışma Zamanı Derlemesi))./clr

Varsayılan olarak, bu işlevin genel durumunun kapsamı uygulama olarak belirlenmiştir. Bu davranışı değiştirmek için bkz. CRT'de Genel durum.

Gereksinimler

Yordam Gerekli başlık
_resetstkoflw <malloc.h>

Daha fazla uyumluluk bilgisi için bkz . Uyumluluk.

Kitaplıklar: CRT kitaplığı özelliklerinin tüm sürümleri.

Örnek

Aşağıdaki örnekte işlevin önerilen kullanımı gösterilmektedir _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 isn't 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;
}

Program bağımsız değişkeni olmayan örnek çıktı:

loop #1

Program, daha fazla yineleme yürütmeden yanıt vermeyi durdurur.

Program bağımsız değişkenleriyle:

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

Tanım

Aşağıdaki örnekte, yapılandırılmış özel durumların C++ özel durumlarına dönüştürüldüğü bir programda önerilen kullanımı _resetstkoflw gösterilmektedir.

Kod

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

Ayrıca bkz.

_alloca