Stackoverflow C boks yapıyor#
C bu iki kod parçaları var#:
İlk
class Program
{
static Stack<int> S = new Stack<int>();
static int Foo(int n) {
if (n == 0)
return 0;
S.Push(0);
S.Push(1);
...
S.Push(999);
return Foo( n-1 );
}
}
İkinci
class Program
{
static Stack S = new Stack();
static int Foo(int n) {
if (n == 0)
return 0;
S.Push(0);
S.Push(1);
...
S.Push(999);
return Foo( n-1 );
}
}
İkisi de aynı şeyi:
Bir Yığın (ikinci bir nesne yığını bir ilk örneğin
<int>genel) oluşturun.Özyinelemeli olarak çağırır ve bir metot n kez (n >= 0) ve her adımda bas 1000 oluşturulan yığın içinde tamsayılar.
Foo(30000) ilk örnek çalıştırdığımda bir istisna, ancak ikinci örnek Foo(1000), n = 1000 çöker oluşur.
CIL Her iki durumda da üretilen gördüğümde tek fark her itmek için boks kısmıydı:
İlk
IL_0030: ldsfld class [System]System.Collections.Generic.Stack`1<int32> Test.Program::S
IL_0035: ldc.i4 0x3e7
IL_003a: callvirt instance void class [System]System.Collections.Generic.Stack`1<int32>::Push(!0)
IL_003f: nop
İkinci
IL_003a: ldsfld class [mscorlib]System.Collections.Stack Test.Program::S
IL_003f: ldc.i4 0x3e7
IL_0044: box [mscorlib]System.Int32
IL_0049: callvirt instance void [mscorlib]System.Collections.Stack::Push(object)
IL_004e: nop
Benim soru: Neden ikinci örneğin yığın CIL önemli aşırı ise, "daha hızlı" ilk daha mı? kaza mı
CEVAP
Neden ikinci örneğin yığın CIL önemli aşırı ise, "daha hızlı" ilk daha mı? kaza mı
Bu notunumarasıbu CIL talimatları doğru bir şekilde kullanılacak iş ya da bellek miktarını temsil etmiyor. Tek bir talimat etkisi çok düşük veya çok yüksek darbe olabilir, ÇİL talimatları sayım ölçmek için doğru bir yol değildir.".
Ayrıca CIL infaz ediliyor ne olduğunun da farkına varırlar. Bu TAM da ÇİL gerçek yürütülen yönergeleri çok daha farklı olabilir yani bir optimizasyon aşaması ile gerçek makine talimatları için CIL derler,,.
Genel olmayan bir koleksiyon kullanıyorsun beri ikinci durumda, Push Her çağrı CIL içinde belirlenen tamsayı kutulu olmasını gerektirir.
Bir tamsayı etkili bir nesne oluşturur boks hangi "Int32. sarar Yerine sadece bir yükleme 32-bit tamsayı üzerine yığını, şimdi yüklemek için bir 32-bit tamsayı üzerine yığını, kutu, etkili de yükler bir nesne başvurusu üzerine yığın.
Eğer Çözümü penceresinde bu incelemek, genel ve genel olmayan sürüm oluşturulan CIL öneriyorsun daha dramatik, çok daha önemli arasındaki farkı görebilirsiniz.
Jenerik etkili bunu gibi bir dizi çağrı olarak derler:
0000022c nop
S.Push(25);
0000022d mov ecx,dword ptr ds:[03834978h]
00000233 mov edx,19h
00000238 cmp dword ptr [ecx],ecx
0000023a call 71618DD0
0000023f nop
S.Push(26);
00000240 mov ecx,dword ptr ds:[03834978h]
00000246 mov edx,1Ah
0000024b cmp dword ptr [ecx],ecx
0000024d call 71618DD0
00000252 nop
S.Push(27);
Genel olmayan, öte yandan, kutulu nesneleri oluşturmak için, ve bunun yerine derler
00000645 nop
S.Push(25);
00000646 mov ecx,7326560Ch
0000064b call FAAC20B0
00000650 mov dword ptr [ebp-48h],eax
00000653 mov eax,dword ptr ds:[03AF4978h]
00000658 mov dword ptr [ebp FFFFFEE8h],eax
0000065e mov eax,dword ptr [ebp-48h]
00000661 mov dword ptr [eax 4],19h
00000668 mov eax,dword ptr [ebp-48h]
0000066b mov dword ptr [ebp FFFFFEE4h],eax
00000671 mov ecx,dword ptr [ebp FFFFFEE8h]
00000677 mov edx,dword ptr [ebp FFFFFEE4h]
0000067d mov eax,dword ptr [ecx]
0000067f mov eax,dword ptr [eax 2Ch]
00000682 call dword ptr [eax 18h]
00000685 nop
S.Push(26);
00000686 mov ecx,7326560Ch
0000068b call FAAC20B0
00000690 mov dword ptr [ebp-48h],eax
00000693 mov eax,dword ptr ds:[03AF4978h]
00000698 mov dword ptr [ebp FFFFFEE0h],eax
0000069e mov eax,dword ptr [ebp-48h]
000006a1 mov dword ptr [eax 4],1Ah
000006a8 mov eax,dword ptr [ebp-48h]
000006ab mov dword ptr [ebp FFFFFEDCh],eax
000006b1 mov ecx,dword ptr [ebp FFFFFEE0h]
000006b7 mov edx,dword ptr [ebp FFFFFEDCh]
000006bd mov eax,dword ptr [ecx]
000006bf mov eax,dword ptr [eax 2Ch]
000006c2 call dword ptr [eax 18h]
000006c5 nop
Burada boks önemini görebilirsiniz.
Senin durumunda bir tamsayı boks kutulu nesne başvurularını yığının üstüne yüklenir neden olur. Benim sistem, bu neden bir stackoverflow üzerinde herhangi bir çağrı daha büyük Foo(127) (32 bit), hangi önerdiği tamsayılar ve kutulu nesne başvurularını (4 bayt her biri) tüm tutuluyor yığında olarak 127*1000*8==1016000, tehlikeli kapatmak için varsayılan değer 1) parçacığı yığın boyutu .NET uygulamaları.
Genel sürüm kullanırken, kutulu bir nesne yok beri, tamsayılar tüm yığında saklı olmak zorunda değil, ve aynı kayıt tekrar ediliyor. Bu recurse önemli ölçüde daha fazla (^sağlar . Yukarı yığın kullanmadan önce benim sistemi 40000).
Bu da/x 64 86, farklı bir JİT olarak CLR sürümü ve platform bağımlı olacak, unutmayın.

Neden Matematik yapıyor.zemin geri bir...
Tam olarak ne yapıyor #0 ..... #endif ...
Neden Matematik yapıyor.yuvarlak(0.499...
Neden Matematik yapıyor.(2.5) dönüş 2 ...
UseCompressedOops JVM bayrağı ne iş ya...