#c# #.net #wpf #64-bit #stack-trace
#c# #.net #wpf #64-разрядный #трассировка стека
Вопрос:
В моем приложении на C # я использовал stacktrace для записи имени метода и файла в случае сбоя.
Существует некоторая разница в трассировке стека между платформами x86 и x64.
public string ErrorMessage
{
set
{
_strErrorMessage = "Error : " value;
//Call the method to log error.
LogError(value);
}
}
В приведенном выше фрагменте кода при установке свойства ErrorMessage я вызываю метод LogError, который захватывает трассировку стека и записывает ее в файл журнала.
MethodA()
{
Logger obj=new Logger();
obj.ErrorMessage="Failure";
}
В этом случае на платформе x86 трассировка стека содержит два стековых фрейма. Один для methodaи другой для установщика свойства ErrorMessage.
На платформе x64 трассировка стека содержит только один stackframe для methodA и отсутствует stackframe для установщика свойства ErrorMessage.
Кто-нибудь может мне объяснить, как происходит оптимизация при получении трассировки стека?
Комментарии:
1. Где
MethodA
происходит вызов? Этот код не завершен.2. Перекрестная публикация: social.msdn.microsoft.com/Forums/en/csharplanguage/thread /…
Ответ №1:
Я не вижу никакой разницы между выводами x64 и x86, когда я пытаюсь получить вывод трассировки стека в тестовом жгуте. (Я не ожидал этого, но я всегда хочу оспорить свои предположения!).
Единственный раз, когда я ожидаю увидеть разницу в стеке вызовов, — это когда вы компилируете код в режиме выпуска. Когда вы делаете это, дрожание часто приводит к встроенным вызовам простых методов, например, установщика вашего свойства. (Да, если вы поразмыслите над своим кодом в режиме выпуска, вы будете по-прежнему видеть отдельные методы; вы увидите это различие только тогда, когда метод JITted)
Для вас это означает, что при отладке установщик появится в стеке вызовов:
at ConsoleApplication5.Program.set_ErrorMessage(String value)
at ConsoleApplication5.Program.MethodA()
at ConsoleApplication5.Program.Main(String[] args)
Но когда вы скомпилируете его в режиме выпуска, код внутри set_ErrorMessage будет встроен в methodA, что означает, что вы увидите только это:
at ConsoleApplication5.Program.MethodA()
at ConsoleApplication5.Program.Main(String[] args)
Эта оптимизация настраивается в свойствах проекта на вкладке Сборка. При переключении между отладкой и выпуском в раскрывающемся списке конфигурации вы увидите разницу в флажке «Оптимизировать код». Да, вы могли бы отключить оптимизацию компилятора для релизных сборок, но тогда вы потенциально снизили бы производительность вашего приложения, чего я бы не рекомендовал.
Ответ №2:
Я подозреваю, что на x64 JIT встраивается (оптимизируется) более агрессивно. Попробуйте выполнить следующее, чтобы убедиться, что это так, или просто запустите в режиме отладки, где оптимизации, влияющие на отладку, должны быть отключены:
public string ErrorMessage
{
[MethodImplAttribute(MethodImplOptions.NoInlining)]
set
{
_strErrorMessage = "Error : " value;
//Call the method to log error.
LogError(value);
}
}
Комментарии:
1. Да, это кажется разумной теорией. 64-разрядный джиттер часто работает иначе, чем 32-разрядный джиттер, вплоть до принимаемых им решений о том, следует ли выполнять встроенные вызовы методов.