问题
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 */
}
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:
- in desktop app / windows service (haven't tried 'metro' apps)
- on WinPhone 8.1 emulator in any mode (release, debug, with or without debugger)
- on real WinPhone 8.1 device (tried on Lumia 625) in debug mode
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.
Is this a bug? Or known limitations of WinPhone? Why it works on emulator? And all this strange "conditions" are important:
Token
must bestruct
, notclass
- It must implement
IDictionary<K,V>
, not any other interface (triedIList<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 insideKeyValuePair<K,V>
. If you do justtoken.Value.GetType()
- it works fine
I created VS 2013 solution to reproduce this situation. It can be downloaded here.
回答1:
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
}
}
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.
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.
来源:https://stackoverflow.com/questions/27079564/windows-phone-8-1-c-sharp-app-critical-crash-executionengineexception-only-on