Pytanie Dlaczego program ze scenariuszem PEVerified Stack Overflow (maxstack) nie powoduje awarii środowiska CLR?


Mogę napisać, skompilować i pomyślnie uruchomić następujący program IL z ustawionym rozmiarem .maxstack na 1, który jest zbyt niski, ponieważ program ma dwie wartości na stosie w jednym punkcie czasu (tj. 2 + 2 == 4). Ten program nie crash w CLR i kończy wykonywanie wszystkich oczekiwanych wyników "Hello World", po których następuje liczba 4.

Jednak ten program (słusznie) nie przekazuje PEVerify wskazującego wyjątek przepełnienia stosu z następującym komunikatem:

Microsoft (R) .NET Framework PE Verifier. Wersja 4.0.30319.18020   Prawa autorskie (c) Microsoft Corporation. Wszelkie prawa zastrzeżone.

[IL]: Błąd: [C: \ tmp \ hello.exe: HelloWorld1.Program :: Main] [offset   0x00000011] Przepełnienie stosu. 1 Błąd (i) Weryfikacja hello.exe

Dlaczego nie ulegnie awarii w CLR?

.assembly extern mscorlib {}
.assembly SampleIL {
    .ver 1:0:1:0
}

.class private auto ansi beforefieldinit HelloWorld1.Program
    extends [mscorlib]System.Object
{
    // Methods
    .method private hidebysig static 
        void Main (
            string[] args
        ) cil managed 
    {
        // Method begins at RVA 0x2050
        // Code size 13 (0xd)
        .maxstack 1 // **** NOTE THIS LINE *****
        .entrypoint

        IL_0000: nop
        IL_0001: ldstr "hello world"
        IL_0006: call void [mscorlib]System.Console::WriteLine(string)
        IL_000b: nop

        ldc.i4 2
        ldc.i4 2
        add
        call void [mscorlib]System.Console::WriteLine(int32)

        IL_000c: ret
    } // end of method Program::Main

    .method public hidebysig specialname rtspecialname 
        instance void .ctor () cil managed 
    {
        // Method begins at RVA 0x205e
        // Code size 7 (0x7)
        .maxstack 8    

        IL_0000: ldarg.0
        IL_0001: call instance void [mscorlib]System.Object::.ctor()
        IL_0006: ret
    } // end of method Program::.ctor

} // end of class HelloWorld1.Program

11
2018-05-29 01:16


pochodzenie


.maxstack deklaruje maksymalną głębokość stosu CLR używanego przez metodę. To nie to samo, co maksymalny rozmiar stosu procesora. Obaj nazywani są stosami, ale nie są tym samym stosem. W szczególności stos CLR jest wyimaginowany. Jest to teoretyczna konstrukcja wirtualnej maszyny. - Raymond Chen
@RaymondChen Dlaczego nie mogłeś opublikować tego zanim skończyłem pisać odpowiedź, która zakładała drugą? :-) - Jonathon Reinhart
@ JonathonReinhart, jeśli usunięta odpowiedź zawiera cenne informacje techniczne, aby uzupełnić naukę, możesz ją cofnąć. Nie jestem pewien, czy usunąłeś go, ponieważ uważasz, że zawiera on błędne informacje, czy też dlatego, że uważasz, że nakładasz się z komentarzem + RaymondChen. - John K
@JohnK Jest niepoprawny. Raymond to wskazał .maxstack nie ma nic wspólnego z rzeczywistym stosem procesora, do którego odnosi się moja odpowiedź. - Jonathon Reinhart
"Ta wartość jest używana głównie przez weryfikację kodu IL i niektóre kompilatory JIT, które chcą wiedzieć z góry, jak głęboki będzie stos IL. " - Raymond Chen


Odpowiedzi:


Odpowiedź wyprowadzona z komentarzy na pytanie przez @RaymondChen

Wspólna infrastruktura językowa (CLI)
Partycja III
Zestaw instrukcji CIL
Ostateczny projekt, kwiecień 2005

1.7.4. Musi dostarczyć maxstack

[... snip ...]
  [Uwaga: Maxstack jest powiązany z   analiza programu, a nie wielkość stosu w czasie wykonywania. To   nie określa maksymalnego rozmiaru w bajtach ramki stosu, ale   raczej liczba elementów, które będą śledzone przez narzędzie do analizy.   nota końcowa]


9
2018-05-29 03:22