11

我可以编写、编译并成功运行以下 IL 程序,其中 .maxstack 大小设置为 1,这太低了,因为该程序在某个时间点在堆栈上有两个值(即 2+2==4)。该程序不会在 CLR 中崩溃,并以“Hello World”的所有预期输出后跟数字 4 完成执行。

但是,该程序将(正确地)不通过 PEVerify,它指出堆栈溢出异常,并显示以下消息:

Microsoft (R) .NET Framework PE 验证程序。版本 4.0.30319.18020 版权所有 (c) Microsoft Corporation。版权所有。

[IL]:错误:[C:\tmp\hello.exe:HelloWorld1.Program::Main][offset 0x00000011] 堆栈溢出。1 验证 hello.exe 的错误

为什么它不会在 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
4

1 回答 1

9

来自@RaymondChen 的问题评论的答案

公共语言基础设施 (CLI)
第 III 部分
CIL 指令集
最终草案,2005 年 4 月

1.7.4 必须提供maxstack

[... snip ... ]
[注:Maxstack与程序分析有关,与运行时堆栈的大小无关。它没有指定堆栈帧的最大大小(以字节为单位),而是指定分析工具应跟踪的项目数。 尾注]

于 2014-05-29T03:22:14.007 回答