【问题标题】:Why does compiler optimization break my code? [duplicate]为什么编译器优化会破坏我的代码? [复制]
【发布时间】:2021-02-01 15:47:28
【问题描述】:

通常,当我制作控制台应用程序时,我会从以下内容开始:

using System;

namespace ColorOptProblemTest
{
    class Program
    {
        const string HELP_TEXT = "";
        static ConsoleColor Default = Console.ForegroundColor;

        static void ShowHelp()
        {
            Console.ForegroundColor = ConsoleColor.Gray;
            Console.WriteLine(HELP_TEXT);
            Console.ForegroundColor = Default;
            Environment.Exit(0);
        }

        static void ThrowError(string Message)
        {
            Console.ForegroundColor = ConsoleColor.Red;
            Console.WriteLine("ERROR: " + Message);
            ShowHelp();
        }

        static void ManageArgs(string[] args)
        {
            switch (args.Length)
            {
                case 0:
                    ThrowError("At least one argument is required.");
                    break;
            }
        }

        static void Main(string[] args)
        {
            ManageArgs(args);
        }
    }
}

重要的是我把Console.ForegroundColor保存起来,等程序退出以后,让终端恢复到原来的颜色。

如果没有编译器优化,代码会按照应有的方式执行所有操作,并且会像魅力一样工作。经过优化,程序退出时,终端颜色为红色。

这可能是优化器中的某种错误吗?也许我只是缺少一些基本的东西。

【问题讨论】:

  • 我看不到您保存和加载前景色的位置。您所说的这种“优化”是什么?你是说 RELEASE 还是 DEBUG?
  • @Steve 在 Release 属性设置中,您可以设置是否要优化。保存是在我将默认设置为 Console.ForegroundColor 的类开始时完成的。加载在退出之前完成。这一切都可以在没有优化的情况下工作,但由于某种原因,经过优化就不行了。
  • 您依赖于不确定的行为来初始化静态字段。见重复。如果您想在更改之前使用该字段保存值,则需要使用确定性机制进行初始化。
  • @PeterDuniho 谢谢。就这样我理解正确:由于优化,静态字段将在使用它们之前的某个时间进行初始化。这就是为什么在没有优化的情况下,程序可以正常工作的原因。如果我理解正确,可以通过向类添加一个空的构造函数来避免这种情况。那么在调用第一个方法后,字段会被初始化吗?还是我需要显式调用构造函数?据我所知,这种延迟初始化是出于性能原因而完成的,因此变量仅在需要时才被初始化,对吗?
  • 是的,一个空的 static 构造函数会在访问任何静态成员(包括静态方法)之前执行,并且当静态构造函数存在时,静态字段初始化确定性完成在执行静态构造函数之前。您不需要(也不能)显式调用静态构造函数。

标签: c# .net compiler-optimization


【解决方案1】:

您根本不需要这样做。而是使用Console.ResetColor() 将颜色重置为进程开始时的颜色。

虽然我认为颜色是您的问题中最少的问题,但请查看您的代码。例如,您不能在不打印帮助文本的情况下输出错误消息,并且您的方法 ThrowError 不会引发错误。将其命名为PrintError 会更贴切。您也不需要在打印帮助文本结束时强制退出,让调用代码控制接下来会发生什么。在许多情况下,这种硬编码行为是不受欢迎的。

【讨论】:

  • 我看不出任何一个回答的问题。第一段提供了另一种选择,但未能真正解释问题所询问的行为。第二段完全是推测性的;它忽略了代码示例作为minimal reproducible example 存在的事实,不一定是命令行程序的实际实现,以及 许多 命令行程序的实现者在事实上使用Environment.Exit() 来立即终止程序而不是将控制权返回给调用者。这是一个标准且完全可以接受的成语。
  • 我从未听说过 Console.ResetColor()。我试试看,谢谢。
猜你喜欢
  • 2016-04-22
  • 2012-08-12
  • 2011-04-13
  • 2020-06-23
  • 2012-10-08
  • 2021-08-15
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多