Приложение 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, которая каким-то образом связана с оптимизацией.

Другие вопросы по тегам