是.NET应用程序中需要的ret指令吗?

Mic*_*tum 19 .net c# clr

我注意到C#编译器retvoid方法结束时生成一条指令:

.method private hidebysig static void Main(string[] args) cil managed
{
    // method body
    L_0030: ret 
} 
Run Code Online (Sandbox Code Playgroud)

我已经为.NET编写了一个编译器,无论我是否发出一个ret语句,它都可以工作(我已经检查了生成的IL,而且确实没有在那里).

我只是想知道:是否需要ret返回void任何方法?它似乎对堆栈没有任何作用,所以我认为这对于void方法来说完全没有必要,但是我想听听那些对CLR有更多了解的人的消息?

Fem*_*ref 22

根据C#标准(ECMA-334),方法定义如下:

方法是实现可由对象或类执行的计算或操作的成员.方法有一个(可能是空的)形式参数列表,一个返回值(除非方法的返回类型为void),并且是静态的或非静态的.

(ECMA-334 ; 8.7.3:方法).

现在,CLI标准定义了以下内容:

控制不允许简单地"落到"方法的结尾.所有路径都应使用以下指令之一终止:ret,throw,jmp或(tail.后跟call,calli或callvirt).

(ECMA-335 ; 12.4,6)

这意味着,在C#中,返回的方法void并不需要一个return语句.然而,当C#编译器编译的C#代码到IL代码,这需要在方法结束时的路径终止,它发出一个ret结束方法.


Tim*_*mwi 17

确实需要这样才能使代码可以验证.否则PEVerify将输出以下错误消息:

[IL]:错误:[(文件名):(方法名称)] [偏移量0x00000000]通过方法结束而不返回


Mar*_*k H 8

来自Ecma-335.(12.4,6)

控制不允许简单地"落到"方法的结尾.所有路径都应使用以下指令之一终止:ret,throw,jmp或(tail.后跟call,calli或callvirt).

  • Ecma-355的标题是"通过SIP隧道传输QSIG" (2认同)