Почему стек становится усеченным в Исключении. StackTrace?

Вы могли бы попробовать ленивое размонтирование:

umount -l
12
задан nightcoder 11 November 2009 в 22:17
поделиться

4 ответа

Хорошо, теперь я понимаю, к чему вы клоните ... Извините за путаницу с встраиванием.

«Стек» в перехваченном исключении - это только дельта от текущего выполняемого блока перехвата до места, где было сгенерировано исключение. Концептуально такое поведение является правильным, поскольку Exception.StackTrack сообщает вам, где возникло исключение в контексте этого блока try / catch. Это позволяет пересылать стеки исключений через «виртуальные» вызовы, сохраняя при этом точность. Классическим примером этого являются исключения .Net Remoting.

Таким образом, если вам нужен полный отчет о стеке в блоке catch, вы должны добавить текущий стек в стек исключения, как в примере ниже. Единственная проблема в том, что это может быть дороже.

    private void InternalMethod()
    {
        try
        {
            ThrowSomething();
        }
        catch (Exception ex)
        {
            StackTrace currentStack = new StackTrace(1, true);
            StackTrace exceptionStack = new StackTrace(ex, true);
            string fullStackMessage = exceptionStack.ToString() + currentStack.ToString();
        }
    }
11
ответ дан 2 December 2019 в 21:44
поделиться

Как сказал csharptest, это сделано специально. StackTrace останавливается на блоке попытки. Более того, в структуре нет перехватчика, который вызывается при возникновении исключения.

Лучшее, что вы можете сделать, - это что-то в этом роде, это абсолютное требование для получения трассировки полного стека (сохранение полной трассировки при создании исключений):

using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Runtime.CompilerServices;
using System.Diagnostics;

namespace ConsoleApplication15 {

    [global::System.Serializable]
    public class SuperException : Exception {

        private void SaveStack() {
            fullTrace = Environment.StackTrace;
        }

        public SuperException() { SaveStack(); }
        public SuperException(string message) : base(message) { SaveStack();  }
        public SuperException(string message, Exception inner) : base(message, inner) { SaveStack(); }
        protected SuperException(
          System.Runtime.Serialization.SerializationInfo info,
          System.Runtime.Serialization.StreamingContext context)
            : base(info, context) { }

        private string fullTrace; 
        public override string StackTrace {
            get {
                return fullTrace;
            }
        }
    }

    class Program {

        public void ExternalMethod() {
            InternalMethod();
        }

        public void InternalMethod() {
            try {
                ThrowIt();
            } catch (Exception ex) {
                Console.WriteLine(ex.StackTrace);
            }
        }

        [MethodImpl(MethodImplOptions.NoInlining)]
        public void ThrowIt() {
            throw new SuperException();
        }


        static void Main(string[] args) {
            new Program().ExternalMethod();
            Console.ReadKey();
        }
    }
}

Выводы:

 
     at System.Environment.get_StackTrace()
   at ConsoleApplication15.SuperException..ctor() in C:\Users\sam\Desktop\Source
\ConsoleApplication15\ConsoleApplication15\Program.cs:line 17
   at ConsoleApplication15.Program.ThrowIt() in C:\Users\sam\Desktop\Source\Cons
oleApplication15\ConsoleApplication15\Program.cs:line 49
   at ConsoleApplication15.Program.InternalMethod() in C:\Users\sam\Desktop\Sour
ce\ConsoleApplication15\ConsoleApplication15\Program.cs:line 41
   at ConsoleApplication15.Program.Main(String[] args) in C:\Users\sam\Desktop\S
ource\ConsoleApplication15\ConsoleApplication15\Program.cs:line 55
   at System.AppDomain._nExecuteAssembly(Assembly assembly, String[] args)
   at Microsoft.VisualStudio.HostingProcess.HostProc.RunUsersAssembly()
   at System.Threading.ExecutionContext.Run(ExecutionContext executionContext, C
ontextCallback callback, Object state)
   at System.Threading.ThreadHelper.ThreadStart()

Невозможно ввести это поведение в существующие исключения, определенные Системой, но .Net имеет богатую инфраструктуру для упаковки исключений и повторного создания, поэтому это не должно быть огромной проблемой.

2
ответ дан 2 December 2019 в 21:44
поделиться

Я знаю, что в блоке catch, если вы выполняете throw ex; , он усекает трассировку стека в этой точке. Возможно, что это сделано «намеренно» для throw, поскольку просто throw; не усекает стек в catch. То же самое может происходить здесь, поскольку вы генерируете новое исключение.

Что произойдет, если вы вызовете фактическое исключение (например, int i = 100/0; )? Трассировка стека все еще усечена?

0
ответ дан 2 December 2019 в 21:44
поделиться

Это часто вызвано оптимизацией компилятора.

Вы можете украсить методы, которые не хотите встраивать, используя следующий атрибут:

[MethodImpl(MethodImplOptions.NoInlining)]
public void ExternalMethod()
{
  InternalMethod();
}
-1
ответ дан 2 December 2019 в 21:44
поделиться
Другие вопросы по тегам:

Похожие вопросы: