释放和调试之间的不同C#输出 [英] Different C# Output Between Release and Debug

查看:150
本文介绍了释放和调试之间的不同C#输出的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我在这里有一个C#程序,在Debug和Release版本之间产生不同的输出。我认为Release版本的空输出符合C#语言规范。这个程序不应该产生输出,而Debug版本。



我从命令行(VS环境之外)运行Release和Debug版本,并获得同样不一致的输出。我反编译Debug版本(使用ILDASM),然后用ILASM重新编译它。当我这样做,新编译的程序的行为就像发布版本。我只能想象,当我解编译然后重新编译一些东西被遗漏,但是我无法确定有什么不同。



关于EXE文件大小:VS生成的Release和Debug版本都有相同的文件大小:5,120个字节。当我解编译和重新编译时,这两个版本的文件大小相同,但文件大小较小:3,072。



程序很小,我看过反射器中的IL,我看不到会导致输出差异的任何东西。



有没有人有一个(希望详细的)解释为什么会有差异?



请注意,我不会尝试使Debug和Release版本一致,一定是我想了解为什么不这样做。



回想一下我上面所说的 - 即使从命令行运行,Debug和Release版本都会产生不同的输出。如果您告诉我,运行时正在为版本版本进行某种优化,但不是针对Debug版本进行某种优化,那么必须在Debug / Release版本组件中嵌入一些内容,告诉运行时才能打开/关闭优化。什么是嵌入某事,为什么在使用ILDASM / ILASM时不会结束?



这里是代码:

 使用系统; 

class Test {
static int value = 0;
static int a = Initialize(Assigning a);
static int b = Initialize(Assigning b);
static String name =Fred;
static int c = Initialize(Assigning c);

static int Initialize(String mssg){
++ value;
Console.WriteLine(In Initialize():: {0},name = {1},返回{2},mssg,name,value);
返回值;
} //初始化()

static void Main(){
} // Main()
} // class Test

这里是Visual Studio生成的Debug版本的输出:

 在Initialize()::分配a,name =,返回1 
在Initialize()::分配b,name =,返回2
在Initialize() :分配c,name = Fred,返回3

运行发行版本不生成输出。 >

解决方案

经过更多的研究,我找到了我正在寻找的答案(感谢Blogbeard指出我在正确的方向)。 >

事实证明,当您为Debug编译时,生成的程序集默认使用DebugableAttribute进行装饰,其调试模式为

  DebuggableAttribute.DebuggingModes.DisableOptimizations | DebugableAttribute.DebuggingModes.Default 

显然这些标志的组合似乎关闭了JIT优化,结果在输出我在Debug版本的程序中看到。程序的发布版本有一个不同的调试模式,允许进行JIT优化。



当然,如果您在AssemblyInfo中手动设置DebuggableAttribute(就像我在测试期间)对于Debug构建,您可以覆盖默认行为。



我确定有一些CLR / JIT律师在那里可以更详细地解释。


I've a little C# program here that produces different output between the Debug and Release versions. The empty output from the Release version is, I think, consistent with the C# Language Specification. This program should not produce output, yet the Debug version does.

I've run both the Release and Debug versions from the command line (outside the VS environment) and get the same inconsistent output. I've decompiled the Debug version (using ILDASM) and then re-compiled it with ILASM. When I do this, the newly compiled program behaves just like the Release version. I can only imagine that when I de-compile and then re-compile something is being left out but I've not been able to determine what's different.

Regarding the EXE file size: Both the Release and Debug versions produced by VS have the same file size: 5,120 bytes. When I de-compile and re-compile, both versions again have the same, but smaller file size: 3,072.

The program is quite small and I've looked at the IL in Reflector and I can't see anything that would cause a difference in output.

Does anyone have a (hopefully detailed) explanation of exactly why there is a difference?

Please note that I'm not trying to make the Debug and Release versions consistent, necessarily, I want to understand why they are not.

Recall what I said above -- both the Debug and Release versions produce different output even when run from the command line. If you tell me the runtime is doing some kind of optimization for the Release version but not for the Debug version then there must be something embedded in the Debug/Release version assemblies that tell the runtime to turn on/off optimizations. What is that embedded "something" and why does it not carry over when using ILDASM/ILASM?

Here's the code:

using System;

class Test {
    static int value = 0;
    static int a = Initialize("Assigning a");
    static int b = Initialize("Assigning b");
    static String name = "Fred";
    static int c = Initialize("Assigning c");

    static int Initialize(String mssg) {
        ++value;
        Console.WriteLine("In Initialize() :: {0}, name={1}, returning {2}", mssg, name, value);
        return value;
    } // Initialize()

    static void Main() {
    } // Main()
} // class Test

And here is the output from the Visual Studio generated Debug version:

In Initialize() :: Assigning a, name=, returning 1
In Initialize() :: Assigning b, name=, returning 2
In Initialize() :: Assigning c, name=Fred, returning 3

Running the release version generates no output.

解决方案

After more research, I found the answer I was looking for (thanks to Blogbeard for pointing me in the right direction).

It turns out that when you compile for Debug, the generated assembly is, by default, decorated with a DebuggableAttribute whose "Debugging Mode" is

DebuggableAttribute.DebuggingModes.DisableOptimizations | DebuggableAttribute.DebuggingModes.Default

It is apparently this combination of flags that seem to turn off JIT optimization, resulting in the output I saw in the Debug version of the program. The Release version of the program has a different "Debugging Mode", allowing JIT optimization to proceed.

Of course, if you manually set the DebuggableAttribute in the AssemblyInfo (as I did during testing) for the Debug build, you can override the default behavior.

I'm sure there are some CLR/JIT Lawyers out there who can explain in greater detail.

这篇关于释放和调试之间的不同C#输出的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆