_resetstkoflw
Yığın taşması kurtarır.
Önemli
Bu API, Windows çalışma zamanı yürütme uygulamalarda kullanılamaz.Daha fazla bilgi için bkz: /zw ile desteklenmeyen crt işlevlerinin.
int _resetstkoflw ( void );
Dönüş Değeri
İşlev başarılı olursa, başarısız olursa sıfır sıfır.
Notlar
_resetstkoflw İşlevi bir yığın taşma koşulunu yerine önemli özel durum hatası ile başarısız olmadan devam etmek bir program izin vererek gelen kurtarır. _resetstkoflw İşlevi çağrılmaz, önceki özel durumdan sonra hiç koruma sayfası vardır. Bir yığın olduğunu sonraki açışınızda overflow, hiç hiçbir özel durum yoktur ve herhangi bir uyarı yapılmadan işlemi sonlandırır.
Bir iş parçacığı bir uygulamada neden olursa bir EXCEPTION_STACK_OVERFLOW özel durum, iş parçacığı sol kendi yığını bozuk bir durumda. Bu gibi diğer özel durumlar, EXCEPTION_ACCESS_VIOLATION veya EXCEPTION_INT_DIVIDE_BY_ZERO, yığını bozuk burada. Program ilk yüklendiğinde yığın çalışmamasını küçük bir değere ayarlanır. Yığın sonra iş parçacığı gereksinimlerini karşılamak için isteğe bağlı olarak büyür. Bu geçerli yığında sonunda page_guard erişimi olan bir sayfa koyarak uygulanır. Daha fazla bilgi için bkz: Guard sayfaları oluşturma.
Bu sayfada adresine işaret edecek şekilde yığın işaretçisi kod neden olduğunda, bir özel durum oluşur ve sistemin üç şunları yapar:
Böylece iş parçacığı okuma ve verileri belleğe yazmayı koruma sayfası page_guard korumasını kaldırır.
Yeni bir koruma ayırır yani bulunduğu bir sayfa altındaki son sayfa.
Özel yönerge yeniden çalıştırır.
Bu yolla, sistem otomatik olarak iş parçacığı için yığın boyutunu artırabilirsiniz. Bir işlemdeki her iş parçacığı en fazla yığın boyutu vardır. Yığın boyutu tarafından derleme zamanında ayarlanır / YIĞINI (yığın ayırma), ya da STACKSIZE proje için .def dosyası deyiminde.
Bu en büyük yığın boyutu aşıldığında, sistem üç şunları yapar:
Koruma sayfasında daha önce açıklandığı gibi page_guard korumasını kaldırır.
Aşağıda en son yeni bir koruma sayfası ayırmak çalışır. Ancak, en büyük yığın boyutunu aştığından bu başarısız.
İş parçacığı özel durum bloğu içinde işleyebilir bir özel durum yükseltir.
Bu noktada, yığın artık koruma sayfası olduğunu, dikkat edin. Program servislerinden uca yığın büyüyor olması gereken yerlerde koruma sayfası, program yığın sonunu yazar ve erişim ihlaline neden oluyor.
Call _resetstkoflw bir yığın taşması özel durumdan sonra kurtarma yapılır her koruma sayfası geri yüklemek için. Bu işlev ana gövdesi içinde çağrılabilir bir __except blok veya dış bir olan blok. Ancak, ne zaman kullanılmalı bazı kısıtlamalar vardır. _resetstkoflwhiçbir zaman dosyasından çağrılabilecek:
Bir filtre ifadesi.
Bir filtre işlevi.
Filtre fonksiyondan çağrılan işlev.
A catch blok.
A __finally block.
Bu noktalarda yığın henüz yeterince unwound değil.
Yığın taşması özel durum oluşturulur yapısal istisna, c++ özel durum değil, bu nedenle _resetstkoflw normal yararlı değil catch bir yığın taşması özel durumu yakalamak değil çünkü engelleyin. Ancak, _set_se_translator olan (ikinci örnekte olduğu gibi) c++ istisnalarını atar bir yapılandırılmış özel durum Çeviricisi uygulamak için kullanılan, c++ catch bloğu tarafından işlenen bir c++ özel durum yığın taşması özel sonuçlanır.
Çağırmak güvenli değil _resetstkoflw , yapılandırılmış özel durum Çevirmen işlevi tarafından oluşturulan bir özel durum gelinen bir c++ catch bloğu içinde. Bu durumda, yığın alanı serbest ve catch bloğunun bile yıkıcı catch bloğu önce destructible nesneler için çağrıldıktan kadar yığın işaretçisi sıfırlanmaz. Bu işlevin yığın alanı serbest bırakılır ve yığın işaretçisi sıfırlama kadar çağrılmamalıdır. Bu nedenle, yalnızca catch bloğu çıktıktan sonra çağrılmalıdır. Gibi küçük mümkün kendisini önceki bir yığın taşması giderilirken catch bloğu içinde oluşan bir yığın taşması kurtarılabilir olduğundan catch bloğu içinde kullanılmalıdır ve catch bloğu taşma catch bloğu içinde bir özel durum, kendisini tetikleyen gibi yanıt vermiyor gibi program tarafından aynı işlenmiş neden yığın alanı.
Bazı durumlarda nerede _resetstkoflw içinde olduğu gibi doğru bir konumda kullanıyor olsa bile, başarısız bir olan blok. Yığın çağırılması sonra bile, yoksa, yine de yürütmek için yeterli yığın alanı sol _resetstkoflw son sayfa yığının içine yazmadan _resetstkoflw son sayfa yığının koruma sayfası ve döndürür hata olduğunu gösteren, 0 olarak sıfırlamak başarısız olur. Bu nedenle, güvenli kullanımı bu işlevin yığın güvenli olduğu varsayılarak dönüş değeri yerine denetimi eklemeniz gerekir.
Yapılandırılmış özel durum işleme değil yakalamak bir STATUS_STACK_OVERFLOW ile uygulama derlendiğinde özel durum /clr veya /clr:pure (bkz: /CLR (ortak dil çalışma zamanı derleme)).
Gereksinimler
Yordamı |
Gerekli başlık |
---|---|
_resetstkoflw |
<malloc.h> |
Daha fazla uyumluluk bilgileri için bkz: Uyumluluk giriş.
Kitaplıklar: tüm sürümleri crt kitaplığı özellikleri.
Örnek
Önerilen kullanımı aşağıdaki örnekte gösterildiği _resetstkoflw işlev.
// 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;
}
Örnek Çıktı
Program bağımsız değişken olmadan:
loop #1
Programı tekrar çalıştırmadan daha fazla yanıt vermiyor.
Program değişkenleri ile:
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ımlama
Önerilen kullanımı aşağıdaki örnekte gösterildiği _resetstkoflw bir programda yapılandırılmış özel durumlar için c++ özel durumlar nerede dönüştürülür.
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;
}
Örnek Çıktı
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.
.NET Framework Eşdeğeri
Yoktur. Standart c işlevi çağırmak için kullanın PInvoke. Daha fazla bilgi için bkz: Platform Çağırma örnekleri.