_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_ZERO
gibi 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 güvenli 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
Açıklama
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.