27

我想知道 .maxstack 是如何工作的。我知道这与您声明的类型的实际大小无关,而是与它们的数量有关。我的问题是:

  1. 这仅适用于函数,还是适用于我们调用的所有函数?
  2. 即使它只是用于声明 .maxstack 的函数,如果你有分支,你怎么知道 maxstack 是什么?您去查看所有“路径”并返回可能的最大值吗?
  3. 如果我将它设置为 16 并且实际上有 17 个变量会发生什么?
  4. 如果我将其设置为 256,是否会有太大的惩罚?
4

3 回答 3

27

.maxstack是 IL 验证的一部分。基本上.maxstack告诉 JIT 它需要为该方法保留的最大堆栈大小。例如,x = y + (a - b)翻译为

(伪 IL:)

1. Push y on the stack
2. Push a on the stack
3. Push b on the stack
4. Pop the last two items from the stack,
      substract them and
      push the result on the stack
5. Pop the last two items from the stack,
      add them and
      push the result on the stack
6. Store the last item on the stack in x and
      pop the last item from the stack

如您所见,每次堆栈中最多有 3 个项目。如果您.maxstack将此方法设置为 2(或更少),则代码将不会运行。

此外,您不能拥有这样的东西,因为它需要无限的堆栈大小:

1. Push x on the stack
2. Jump to step 1

要回答您的问题:

  1. 这仅适用于函数,还是适用于我们调用的所有函数?

只为功能

  1. 即使它只是用于声明 .maxstack 的函数,如果你有分支,你怎么知道 maxstack 是什么?您去查看所有“路径”并返回可能的最大值吗?

您去查看所有路径并返回可能的最大值

  1. 如果我将它设置为 16 并且实际上有 17 个变量会发生什么?

它与变量的数量无关,请参阅Lasse V. Karlsen的回答

  1. 如果我将其设置为 256,是否会有太大的惩罚?

似乎不是一个好主意,但我不知道。

你真的需要自己计算.maxstack吗?System.Reflection.Emit为你计算它IIRC。

于 2009-08-07T08:35:20.623 回答
6

它与声明的变量数量无关,而是与在任何给定时间需要将多少值压入堆栈以计算某些表达式有关。

例如,在以下表达式中,我假设需要将 2 个值推入堆栈:

x = y + z;

这与至少存在 3 个变量 x、y 和 z 以及可能还有其他变量这一事实无关。

不幸的是,我不知道您其他问题的答案,我想实验将是找到一些答案的一种方法。

于 2009-08-06T20:45:13.847 回答
0

您可以参考以下内容和 ECMA STANDARD 以获得更好的理解:

void  msd(string a,
  string b,
  string c,
  string d,
  string e)
  {
  Console.WriteLine(a);
}

msd("a","b","c","d","e");

当我跑步时,ildasm.exe我得到了这个:

{
  .entrypoint
  // Code size       40 (0x28)
  .maxstack  8
  IL_0000:  nop
  IL_0001:  nop
  IL_0002:  ldstr      "a"
  IL_0007:  ldstr      "b"
  IL_000c:  ldstr      "c"
  IL_0011:  ldstr      "d"
  IL_0016:  ldstr      "e"
  IL_001b:  call       void sf.Program::'<Main>g__msd|0_0'(string,
                                                           string,
                                                           string,
                                                           string,
                                                           string)
  IL_0020:  nop
  IL_0021:  call       string [mscorlib]System.Console::ReadLine()
  IL_0026:  pop
  IL_0027:  ret
} // end of method Program::Main

从上面。我找到了stakc不是由 push & pop 指令确定的最大值。

我不知道真正的堆栈编号值是多少。所以,我参考ildasm反汇编代码来确定真正的最大堆栈值。

于 2018-01-19T01:39:04.657 回答