Приложение Windows Phone 8.1 C#: критический сбой (ExecutionEngineException) только на реальном устройстве в режиме выпуска
Представьте себе следующий тип структуры:
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 во всех методах / свойствах. Он размещен в отдельной переносимой библиотеке классов.
Затем представьте себе использование этой структуры:
var token = new Token("111");
var kvp = new KeyValuePair<string, Token>("aaa", token);
var val = kvp.Value.Value;
var t = val.GetType(); // XXX
Этот код прекрасно работает практически везде:
- в настольном приложении / службе Windows (еще не пробовал приложения в метро)
- на эмуляторе WinPhone 8.1 в любом режиме (выпуск, отладка, с отладчиком или без него)
- на реальном устройстве WinPhone 8.1 (пробовал на Lumia 625) в режиме отладки
Но когда я запускаю этот код на реальном устройстве WP 8.1 (Lumia 625, последние обновления) в режиме RELEASE, я получаю ExecutionEngineException
исключение в строке XXX
с сообщением An unhandled exception of type 'System.ExecutionEngineException' occurred in Unknown Module.
Это исключение не может быть поймано и не содержит никаких деталей - приложение просто вылетает.
Это ошибка? Или известные ограничения WinPhone? Почему это работает на эмуляторе? И все эти странные "условия" важны:
Token
должно бытьstruct
неclass
- Он должен реализовать
IDictionary<K,V>
, не любой другой интерфейс (пробовалIList<Token>
,ICollection
) - Он должен быть помещен в отдельную переносимую библиотеку классов. Если я перенесу его в проект WP 8.1 - он отлично работает
- Экземпляр
Token
должны быть размещены внутриKeyValuePair<K,V>
, Если вы простоtoken.Value.GetType()
- отлично работает
Я создал решение VS 2013, чтобы воспроизвести эту ситуацию. Его можно скачать здесь.
1 ответ
Я создал отчет об ошибках в Microsoft Connect пару месяцев назад и ждал ответа, но не похоже, что кто-то в Microsoft заинтересован в исправлении этой ошибки.
Кстати, я создал более простое воспроизведение:
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
определение и использование) могут быть расположены в одной сборке.
Я также заметил, что добавление MethodImpl(MethodImplOptions.NoOptimization)
атрибут метода, который использует Token
устраняет проблему, поэтому даже если учесть, что я не гуру.NET, я на 99% уверен, что это ошибка компилятора (C#, MDIL, NGEN и т. д.) для ARM, которая каким-то образом связана с оптимизацией.