Kaç tane iç içe işlev çağrısı var?


15

MSDN'den StackOverflowException hakkında alıntı :

Çok fazla iç içe yöntem çağrısı içerdiğinden, yürütme yığını taşdığında atılan kural dışı durum.

Too manyburada oldukça belirsiz. Çok fazla kişinin gerçekten çok fazla olduğunu nasıl bilebilirim? Binlerce işlev çağrısı? Milyonlarca? Bilgisayardaki bellek miktarıyla bir şekilde ilişkili olması gerektiğini varsayıyorum, ancak kabaca doğru bir büyüklük sırası bulmak mümkün mü?

Bu konuda endişeliyim çünkü özyinelemeli yapıların ve özyinelemeli fonksiyon çağrılarının yoğun kullanımını içeren bir proje geliştiriyorum. Küçük testlerden daha fazlası için kullanmaya başladığımda uygulamanın başarısız olmasını istemiyorum.


4
Özyinelemeli bir işlevi özyinelemeli olmayan bir işleve dönüştürmek nispeten kolaydır. Sadece bir Stack<T>.
Brian

1
"Çok fazla" ne kadar büyük olduğunu tanımlamak tamamen size bağlıdır. .NET için kullanın editbin /stack:WHATEVER-NUMBER-YOU-LIKE yourexefile.exe.
SK-logic

Yanıtlar:


28

Bu konuda endişeliyim çünkü özyinelemeli yapıların ve özyinelemeli fonksiyon çağrılarının yoğun kullanımını içeren bir proje geliştiriyorum. Küçük testlerden daha fazlası için kullanmaya başladığımda uygulamanın başarısız olmasını istemiyorum.

Dil çevre desteklediği sürece kuyruk çağrı optimizasyonu (ve özyineleme olan bir kuyruk arama), başparmak temel kural şudur: yineleme derinliği O (log n) yani dayalı algoritmalar veya veri yapılarını kullanarak olması garanti edilmelidir böl-ve- fetih (ağaçlar gibi, çoğu sıralama alogorithms, vb.) TAMAM, ama doğrusal bir şey (bağlantılı liste işleme özyinelemeli uygulamaları gibi) değildir.


3
+1. Çok iyi bir cevap, dolaylı olarak bu kuralı kullanıyorum ama bunun farkında değildim.
Giorgio

Bu gün ve yaşta, hemen hemen sıfat ifadesine layık herhangi bir üretim kalitesi derleyicisi kuyruk çağrısı optimizasyonunu destekleyecektir.
John R. Strohm

1
@ JohnR.Strohm Ancak OP, .NET sorusunu etiketledi, bu yüzden AFAIK yalnızca 64 bitlik jitter şu anda kuyruk çağrı optimizasyonu yapıyor.
Mark Hurd

1
Sadece karışıklık yok, x86 ve x64 her zaman CIL "kuyruğunu" onurlandırıyor. yönerge öneki. Özetlemek gerekirse, .NET arazisinde F #, kuyruk çağrısı optimizasyonunu tamamlar, C # yapmaz ve x64 jitter "kolay" ise (bağımlı olamaz) yapar. Bkz. Blogs.msdn.com/b/clrcodegeneration/archive/2009/05/11/…
Stephen Swensen

1
Doğru, ancak bazı durumlarda, ASP.NET'i barındıran rezil bir IIS'de olduğu gibi, neredeyse tüm O (log n) özyineleme derinliği bile, neredeyse tüm özyineleme (veya özyinelemesiz iç içe çağrıların uzun bir zinciri bile) imkansız. Etraftaki tek yol iis binary'nin kendisini düzenlemek.
SK-logic

17

Varsayılan olarak, CLR her iş parçacığı için yığına 1 MB ayırır ( bu makaleye bakın ). Ancak, bu miktarı aşmak için gereken birçok çağrı. Bu, parametreler ve yerel değişkenler gibi şeyler için her çağrının yığın üzerinde ne kadar alan kullandığına bağlı olarak değişir.

StackOverflowExceptionBiraz alışılmışın dışında olmaya istekliyseniz, tek bir çağrı ile a atabilirsiniz :

private static unsafe void BlowUpTheStack()
{
    var x = stackalloc byte[1000000000];
    Console.WriteLine("Oh no, I've blown up the stack!");
}

Ne yazık ki, bu makul varsayılan genellikle ihlal edilir (örneğin, asp.net'te).
SK-logic

2

Yana Cole Campbell kaydetti bellek boyutu ve Michael Borgwardt kaydetti kuyruk çağrı optimizasyonu O karşılamaz.

Dikkat edilmesi gereken bir diğer şey ise CPS kuyruk çağrı optimizasyonu tek fonksiyonlar içindir birkaç örülmüş fonksiyonlarını optimize etmek için kullanılabilir.

Burada yaptığımız gibi yığının boyutunu artırabilir ve 64 bit kodun 32 bit koddan daha hızlı yediğini unutmayın.

Not, F # interaktif altındaki örneklerden birini, yığını üflemeden 40 saatten fazla bir süre boyunca çalıştırdık. Evet, başarılı bir şekilde tamamlanmaya sürekli olarak giden bir işlev çağrısıydı.

Ayrıca, sorunların nerede oluştuğunu anlamak için kod kapsamı yapmanız gerekiyorsa ve VS ile kullanabileceğiniz kod kapsamına sahip değilseniz, TestDriven.NET

Sitemizi kullandığınızda şunları okuyup anladığınızı kabul etmiş olursunuz: Çerez Politikası ve Gizlilik Politikası.
Licensed under cc by-sa 3.0 with attribution required.