偶然明白了Release和Debug的一点区别
2008-05-10 15:47
399 查看
在这之前,让我说出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,
[3] string s,
[4] bool 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,
[2] string 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是完整的,单步跟踪也跟进去了。恍然大悟。。。
源码如下:
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,
[3] string s,
[4] bool 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,
[2] string 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是完整的,单步跟踪也跟进去了。恍然大悟。。。
相关文章推荐
- 项目Debug版本与Release版本的区别
- Debug与Release的区别
- 关于Debug和Release之本质区别
- Debug和Release有什么区别
- VC下Debug和Release区别
- Debug与Release版本的区别详解
- Debug和Release区别
- Visual Studio中的debug和release版本的区别
- Debug 和 Release 编译方式的本质区别
- VS 程序调试--Debug和Release区别
- Debug和Release有什么区别
- VS中Debug模式和Release模式的区别
- 关于Debug和Release的区别之讨论
- ios应用:release与debug编译方式的区别
- Debug和Release区别
- vs 项目发布Debug和Release区别
- C#中的项目文件夹debug 和release的区别
- VS2008 Debug与Release的本质区别(转)
- Debug 和 Release 编译方式的本质区别
- VC++中debug跟release编译模式的区别总结