偶然明白了Release和Debug的一点区别

在这之前,让我说出Release和Debug编译出的软件的区别,我还真的只能说写套话,没有什么深入的了解和实际的感触。最近研究MSIL,在写一段C#代码出现了点手误。就是这个失误,透过MSIL,让我从一个方面了解了二者的区别。

源码如下:

 

             int  x, y, z;
            
string  s;

            Console.WriteLine(
" Enter x: " );
            s 
=  Console.ReadLine();
            x 
=  Int32.Parse(s);

            Console.WriteLine(
" Enter y: " );
            s 
=  Console.ReadLine();
            y 
=  Int32.Parse(s);

            
if  (x  <  y)
                z 
=  x;
            
else
                z 
=  y;

            Console.WriteLine(
" {0:d}, z " );

很容易看到,手误在最后一行,我的本意是输出z的值。由于引号的位置错了,这样的输出就变成了:{0:d}, z。这样if...else一段根本是没用的。

Debug编译出来的MSIL代码是这样的:

.method  private  hidebysig  static   void   Main( string [] args) cil managed
{
  .entrypoint
  
// Code size       80 (0x50)
  .maxstack  2
  .locals init ([
0] int32 x,
           [
1] int32 y,
           [
2] int32 z,
           [
3string s,
           [
4bool CS$4$0000)
  IL_0000:  nop
  IL_0001:  ldstr      
"Enter x:"
  IL_0006:  call       
void [mscorlib]System.Console::WriteLine(string)
  IL_000b:  nop
  IL_000c:  call       
string [mscorlib]System.Console::ReadLine()
  IL_0011:  stloc.
3
  IL_0012:  ldloc.
3
  IL_0013:  call       int32 [mscorlib]System.Int32::Parse(
string)
  IL_0018:  stloc.
0
  IL_0019:  ldstr      
"Enter y:"
  IL_001e:  call       
void [mscorlib]System.Console::WriteLine(string)
  IL_0023:  nop
  IL_0024:  call       
string [mscorlib]System.Console::ReadLine()
  IL_0029:  stloc.
3
  IL_002a:  ldloc.
3
  IL_002b:  call       int32 [mscorlib]System.Int32::Parse(
string)
  IL_0030:  stloc.
1
  IL_0031:  ldloc.
0
  IL_0032:  ldloc.
1
  IL_0033:  clt
  IL_0035:  ldc.i4.
0
  IL_0036:  ceq
  IL_0038:  stloc.s    CS$
4$0000
  IL_003a:  ldloc.s    CS$
4$0000
  IL_003c:  brtrue.s   IL_0042
  IL_003e:  ldloc.
0
  IL_003f:  stloc.
2
  IL_0040:  br.s       IL_0044
  IL_0042:  ldloc.
1
  IL_0043:  stloc.
2
  IL_0044:  ldstr      
"{0:d}, z"
  IL_0049:  call       
void [mscorlib]System.Console::WriteLine(string)
  IL_004e:  nop
  IL_004f:  ret
}
  //  end of method Program::Main

Release编译出来的就简单多了,而且也没有nop操作:

.method  private  hidebysig  static   void   Main( string [] args) cil managed
{
  .entrypoint
  
// Code size       61 (0x3d)
  .maxstack  2
  .locals init ([
0] int32 x,
           [
1] int32 y,
           [
2string s)
  IL_0000:  ldstr      
"Enter x:"
  IL_0005:  call       
void [mscorlib]System.Console::WriteLine(string)
  IL_000a:  call       
string [mscorlib]System.Console::ReadLine()
  IL_000f:  stloc.
2
  IL_0010:  ldloc.
2
  IL_0011:  call       int32 [mscorlib]System.Int32::Parse(
string)
  IL_0016:  stloc.
0
  IL_0017:  ldstr      
"Enter y:"
  IL_001c:  call       
void [mscorlib]System.Console::WriteLine(string)
  IL_0021:  call       
string [mscorlib]System.Console::ReadLine()
  IL_0026:  stloc.
2
  IL_0027:  ldloc.
2
  IL_0028:  call       int32 [mscorlib]System.Int32::Parse(
string)
  IL_002d:  stloc.
1
  IL_002e:  ldloc.
0
  IL_002f:  ldloc.
1
  IL_0030:  pop
  IL_0031:  pop
  IL_0032:  ldstr      
"{0:d}, z"
  IL_0037:  call       
void [mscorlib]System.Console::WriteLine(string)
  IL_003c:  ret
}
  //  end of method Program::Main

我一开始使用Release编译的,感觉很奇怪,明显if...else一段就没有编译。我想怪哉了。然后运行了一下,发现结果是“{0:d},z"。发现了最后一行的手误,这一手误直接导致if...else一段成了垃圾代码。然后用F11单步跟踪,if...else那段代码根本就是整体跳过。于是换Debug模式编译,发现编译出来的MSIL的if...else是完整的,单步跟踪也跟进去了。恍然大悟。。。

你可能感兴趣的:(了无秘密)