MethodNotFound, синглтон-класс и «оптимизировать код» - PullRequest
2 голосов
/ 09 января 2010

Я пишу приложение .net compact framework на c #. Он отлично работал в среде разработки, но при сборке в режиме релиза и запуске сам по себе генерировал исключения MethodNotFound. Я набросал кучу отладочного кода, чтобы выяснить, где он ломался, и сузил его до большой функции Init (). Это, в свою очередь, вызывает методы для нескольких одноэлементных классов, которые реализованы следующим образом:

private SingletonClass() {}

private static readonly SingletonClass _instance = new SingletonClass();
public static SingletonClass Instance
{
 get
 {
  return _instance;
 }
}

Одна вещь, которую я заметил, состоит в том, что запись отладки от конструктора в классе singleton будет записываться в журнал перед первой записью в функции Init (). Похоже, что во время выполнения движок что-то делал под капотом, прежде чем он фактически запустил мой код.

Как только у меня было «достаточно» отладочного кода в этих одноэлементных классах, он не вызывал бы исключение MethodNotFound, и программа работала бы нормально. Я говорю «достаточно», потому что я могу закомментировать код отладки и получить MethodNotFound. Когда я снова прокомментировал это, это сработало.

Странная часть заключается в том, что когда исключение было не , то записи журнала отладки были бы в том порядке, в котором их вызывал мой код. Это было похоже на то, что движок во время выполнения не выполнял свою работу «под капотом», как это было, когда выбрасывался MethodNotFound.

Я попытался очистить опцию «Оптимизировать код» в проекте, в котором были классы синглтона, и, похоже, проблема решена. (Сначала я попробовал это, но научился тому, как варианты проекта в пользовательском интерфейсе не влияют на проект бизнес-логики.)

В нескольких постах о MethodNotFound, которые я нашел, говорилось о недостающих библиотеках DLL, неправильных версиях DLL или нехватке памяти.

Я нашел пост, в котором рассказывается о том, как компилятор работает со статическими элементами, используемыми в синглтон-классах.

http://www.yoda.arachsys.com/csharp/singleton.html

Я думаю, это связано с проблемой, с которой я столкнулся, но в конце концов мне пришлось очистить «оптимизировать код», чтобы заставить его работать.

Итак, мой вопрос, что, черт возьми, происходит? Это работает, так что это академический вопрос на данный момент. Надеюсь, это избавит кого-то еще от головной боли.

1 Ответ

2 голосов
/ 11 января 2010

Используете ли вы отражение в вашем коде для обхода стека вызовов? (поиск классов StackFrame или StackTrace)

Небольшие функции часто встроены при оптимизации кода, что означает, что определенные методы могут полностью исчезать из стека вызовов в сборке выпуска. Если вы ожидаете, что этот метод будет присутствовать в стеке вызовов, вы можете увидеть встраивание.

Когда вы добавляете код отладки в небольшую функцию, я предполагаю, что JIT перестает оценивать ее как встроенную функцию, и поэтому метод возвращается в стек вызовов, и ваша проблема исчезает.

Вы можете пометить метод как неотключаемый с помощью атрибута CompilerServices.MethodImpl . попробуйте применить это к одной из ваших функций, которая была «исправлена», добавив код отладки.

Смотри также http://blogs.msdn.com/davidnotario/archive/2004/11/01/250398.aspx

...