【问题标题】:Static member variable not being initialized in Release - Compiler/clr bug?静态成员变量未在 Release 中初始化 - 编译器/clr 错误?
【发布时间】:2010-08-26 22:50:39
【问题描述】:

我在调试模式下的预期输出和输出,以及在 VS2010、.NET 4.0 下的发布模式:

bar construct
main

在发布模式下输出不是在VS2010调试器下,在WinDbg下:

main

程序在 VS2005、.NET 2.0 上没有表现出这种行为

using System;

namespace static_init
{
    public class bar
    {
        public bar()
        {
            Console.WriteLine("bar construct");
        }
    }

    class Program
    {
        public static bar blah = new bar();

        static void Main(string[] args)
        {
            Console.WriteLine("main");
            Console.ReadLine();
        }
    }
}

可能相关: Static constructor can run after the non-static constructor. Is this a compiler bug?

更新

在我的实际代码构造函数中,bar() 使用 C++(非托管)初始化了一些互操作代码。它需要在这个库中的任何其他内容之前发生 - 有什么方法可以确保无需在库中放入涉及所有静态(具有未外部引用的副作用)的 init() 函数?

未来搜索者的注意事项:我使用的是 SWIG,这是他们在包装器生成代码中做出的假设。 SWIGStringHelper 是当前的罪犯,但可能还有更多。

结论

更新到 SWIG 的 2.0 版,它根据新版本 .NET 的需要放入静态构造函数。

【问题讨论】:

  • 非常感谢“更新”和“结论”——我有非常相似的场景,也使用了旧的 SWIG 1.3.40——刚刚更新到 2.0.9,一切正常。 “结论”为我节省了大量的调查时间!

标签: c# .net-4.0 clr


【解决方案1】:

它可能正在优化,因为你不使用它。

这也不是编译器错误,它在语言规范中。

17.4.5.1静态字段初始化

静态字段变量初始化器 一个类声明对应一个 分配的顺序是 以文本顺序执行,其中 它们出现在类声明中。 如果是静态构造函数(§17.11) 存在于类中,执行 静态字段初始化器发生 在执行该操作之前 静态构造函数。否则,该 执行静态字段初始化程序 在依赖于实现的时间 在第一次使用静态之前 该类的字段

由于您从不使用 Program 类的静态字段,因此不能保证静态初始化程序运行(尽管它可以...上面的“依赖于实现的时间”)

更新
你可以通过让 Program 有一个静态构造函数来完成你想要的。

static Program (){} 或者可能通过访问另一个(可能是虚拟的)静态变量

【讨论】:

    【解决方案2】:

    请注意,.NET 4.0 在静态初始化方面有一些变化。 Jon Skeet 写了一篇包含一些示例的博客文章:

    Type initialization changes in .NET 4.0

    如果你想要精确的初始化,你应该使用静态构造函数(可能为空)。

    using System;
    
    namespace static_init
    {
        public class bar
        {
            public bar()
            {
                Console.WriteLine("bar construct");
            }
        }
    
        class Program
        {
            public static bar blah = new bar();
    
            // This static constructor will make sure that the type Program 
            // is initialized before it is first used.
            //
            static Program()
            { }
    
            static void Main(string[] args)
            {
                Console.WriteLine("main");
                Console.ReadLine();
            }
        }
    }
    

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2023-04-02
      相关资源
      最近更新 更多