Windows Phone 8.1 C#应用:严重崩溃(ExecutionEngineException)仅在发布模式下的真实设备上

Windows Phone 8.1 C#应用:严重崩溃(ExecutionEngineException)仅在发布模式下的真实设备上

问题描述:

想象一下以下结构类型:

Imagine the following struct type:

public struct Token : IDictionary<string, Token>
{
    public readonly object Value;
    public Token(string str) { Value = str; }
    public Token(IDictionary<string, Token> dict) { Value = dict; }

    /* IDictionary<string, Token> implementation is here */
}

不要问我任何有关它的作用的信息.实现并不重要,您可以在所有方法/属性中引发NotImplementedException.它放置在单独的可移植类库中.

Don't ask me anything about what it does. Implementation doesn't matter, you can throw NotImplementedException in all methods/properties. It is placed in separate portable class library.

然后想象一下该结构的用法:

Then imagine the usage of this struct:

var token = new Token("111");
var kvp = new KeyValuePair<string, Token>("aaa", token);
var val = kvp.Value.Value;
var t = val.GetType(); // XXX

此代码几乎可以在所有地方完美运行:

This code works perfectly almost everywhere:

  • 在桌面应用程序/Windows服务中(未尝试过地铁"应用程序)
  • 在任何模式下(发行版,调试版,有无调试器)在WinPhone 8.1模拟器上
  • 在调试模式下的实际WinPhone 8.1设备(在Lumia 625上试用)上

但是,当我在RELEASE模式下在真正的WP 8.1设备(Lumia 625,最新更新)上运行此代码时,我在第XXX行收到了ExecutionEngineException异常,消息为An unhandled exception of type 'System.ExecutionEngineException' occurred in Unknown Module.,无法捕获此异常,并且不包含任何详细信息-应用会崩溃.

But when I run this code on real WP 8.1 device (Lumia 625, latest updates) in RELEASE mode, then I get ExecutionEngineException exception at line XXX with message An unhandled exception of type 'System.ExecutionEngineException' occurred in Unknown Module. This exception can't be caught and doesn't contain any details - app just crashes.

这是一个错误吗?还是WinPhone的已知限制?为什么它可以在模拟器上运行?所有这些奇怪的条件"都很重要:

Is this a bug? Or known limitations of WinPhone? Why it works on emulator? And all this strange "conditions" are important:

  • Token必须是struct,而不是class
  • 它必须实现IDictionary<K,V>,而不是其他任何接口(尝试过IList<Token>ICollection)
  • 必须将其放置在单独的可移植类库中.如果我在WP 8.1项目中将其移动-效果很好
  • Token的实例必须放置在KeyValuePair<K,V>内部.如果您只是token.Value.GetType()-效果很好
  • Token must be struct, not class
  • It must implement IDictionary<K,V>, not any other interface (tried IList<Token>, ICollection)
  • It must be placed in separate portable class library. If I move it in WP 8.1 project - it works fine
  • Instance of Token must be placed inside KeyValuePair<K,V>. If you do just token.Value.GetType() - it works fine

我创建了VS 2013解决方案来重现这种情况.可以在此处下载>.

I created VS 2013 solution to reproduce this situation. It can be downloaded here.

我创建了

I created the error report at Microsoft Connect couple months ago and have been waiting for response but it doesn't look that somebody in Microsoft is interested in fixing this bug.

通过这种方式,我创建了一个更简单的副本:

By the way I created a more simple repro:

public struct Token : IDictionary<string, Token>
{
    /* IDictionary<string, Token> implementation is here */
}
public static class Test
{
    //[MethodImpl(MethodImplOptions.NoOptimization)]
    public static void Method()
    {
        var dict = new Dictionary<string, Token> { { "qwe", new Token() } };
        var arr = dict.ToArray(); // XXX        
    }
}

IDictionary<string, Token>的实现无关紧要,例外发生在第XXX行.并且它们(Token的定义和用法)可以位于一个程序集中.

Implementation of IDictionary<string, Token> doesn't matter, the exception occurs at line XXX. And they (Token definition and usage) can be located in one assembly.

我还注意到,将MethodImpl(MethodImplOptions.NoOptimization)属性添加到使用Token的方法可以解决此问题,因此即使考虑到我不是.NET专家,我也有99%的把握确保它是编译器中的错误(C#,MDIL,NGEN等)与优化相关的ARM.

I also noticed that adding the MethodImpl(MethodImplOptions.NoOptimization) attribute to a method that uses Token fixes the problem, so even considering that I'm not a .NET guru I'm 99% sure that it is a bug in compiler (C#, MDIL, NGEN, whatever) for ARM that is somehow related to optimizations.