Мы находимся в процессе миграции приложения на .NET 4.0 (с версии 3.5). Одна из проблем, с которыми мы сталкиваемся, воспроизводима только в очень специфических условиях:
- Только в сборке выпуска
- Только с включенной оптимизацией и / или отладочной информацией, установленной только для pdb.
Я имею в виду, что если я отключу оптимизацию и , установив отладочную информацию на полную, проблема исчезнет.
Рассматриваемый код прекрасно работает в .NET 3.5, в режиме выпуска с включенной оптимизацией и т. Д. И работает в течение длительного времени.
Я действительно не хочу предполагать, что в компиляторе C # есть ошибка, поэтому на самом деле у меня вопрос, есть ли какие-нибудь методы, которые я могу использовать для отслеживания того, что мы можем делать неправильно, чтобы вызвать неправильную оптимизацию? *
Я пытаюсь сузить эту проблему до небольшого тестового примера, чтобы я мог опубликовать здесь некоторый код.
Edit:
Я отследил проблему до следующего:
У нас есть этот код в конструкторе формы:
public ConnectionForm()
{
LocalControlUtil.Configure("ConnectionForm", "Username", usernameLabel);
LocalControlUtil.Configure("ConnectionForm", "Password", passwordLabel);
LocalControlUtil.Configure("ConnectionForm", "Domain", domainLabel);
LocalControlUtil.Configure("ConnectionForm", "Cancel", cancelButton);
LocalControlUtil.Configure("ConnectionForm", "OK", okButton);
}
Эти вызовы относятся к некоторому пользовательскому коду локализации. Конструктор для этой формы вызывается из другой сборки. Метод LocalControlUtil.Configure
вызывает Assembly.GetCallingAssembly()
, который возвращает правильное значение для всех вышеперечисленных вызовов, , кроме последнего .
Я могу изменить порядок строк выше, добавить новые или удалить текущие, и каждый раз, когда это последняя строка, которая не работает.
Я предполагаю, что это JIT, вставляющий последний вызов метода в место, где был вызван конструктор (в другой сборке). Добавление [MethodImpl(MethodImplOptions.NoInlining)]
в конструктор выше устраняет проблему.
Кто-нибудь знает, почему это происходит? Мне кажется странным, что только последняя строка может быть вставлена. Это новое поведение в .NET 4.0?
Редактировать 2:
Я теперь сузил это до устранения хвостового вызова, я полагаю, вызванного новым материалом хвостового вызова в .NET 4 .
В приведенном выше коде последний вызов LocalControlUtil.Configure
в конструкторе исключается и помещается в вызывающий метод, который находится в другой сборке. Поскольку метод вызывает Assembly.GetCallingAssembly
, мы не вернем правильную сборку.
Есть ли какой-нибудь способ остановить компилятор (или JIT или что-то еще) от устранения хвостового вызова?