본문 바로가기
C#

[C#] StackTrace, StackFrame

by DANEW 2023. 10. 24.

StackTrace 클래스

 

StackTrace 클래스 (System.Diagnostics)

여러 스택 프레임의 정렬된 컬렉션에 해당하는 스택 추적을 나타냅니다.

learn.microsoft.com

namespace System.Diagnostics
{
    public class StackTrace
    {
        public StackTrace();
        public StackTrace(bool fNeedFileInfo);
        public StackTrace(int skipFrames);
        public StackTrace(Exception e);
        public StackTrace(StackFrame frame);
        public StackTrace(int skipFrames, bool fNeedFileInfo);
        public StackTrace(Exception e, bool fNeedFileInfo);
        public StackTrace(Exception e, int skipFrames);
        // public StackTrace(Thread targetThread, bool needFileInfo);
        public StackTrace(Exception e, int skipFrames, bool fNeedFileInfo);
 
        public virtual int FrameCount { get; }
 
        public virtual StackFrame GetFrame(int index);
        public virtual StackFrame[] GetFrames();
 
        public override string ToString();
    }
}

StackFrame 클래스

반응형
 

StackFrame 클래스 (System.Diagnostics)

현재 스레드의 호출 스택에 대한 함수를 나타내는 StackFrame에 대한 정보를 제공합니다.

learn.microsoft.com

namespace System.Diagnostics
{
    public class StackFrame
    {
        public const int OFFSET_UNKNOWN = -1;
 
        public StackFrame();
        public StackFrame(bool fNeedFileInfo);
        public StackFrame(int skipFrames);
        public StackFrame(int skipFrames, bool fNeedFileInfo);
        public StackFrame(string fileName, int lineNumber);
        public StackFrame(string fileName, int lineNumber, int colNumber);
 
        public virtual MethodBase GetMethod();
 
        public virtual int GetFileColumnNumber();
        public virtual int GetFileLineNumber();
        public virtual string GetFileName();
 
        public virtual int GetILOffset();
        public virtual int GetNativeOffset();
 
        public override string ToString();
    }
}

- StackTrace와 StackFrame 클래스는 실행 호출 스택에 대한 읽기 전용 시각(View)를 제공
- 현재 스레드, 현재 프로세스의 다른 스래드, Excption 객체의 스택 궤적(Stack Trace)를 얻을 수 있음
- 진단 작업에 유용, 핵(Hack)으로 사용도 가능
- StackTrace: 전체 호출 스택
- StackFrame: 스택 안에 개별 메서드 호출을 나타냄

- 인수 없이, 혹은 bool 인수 하나만 지정해서 StackTrace 인스턴스를 생성하면
  현재 스레드의 호출 스택의 스냅숏을 얻게 됨
 * bool 인수를 true로 지정하면 StackTrace는 확장자가 .pdb인 프로젝트 디버그 파일을 읽어들임
 * 호출의 파일 이름, 행 번호, 열 오프셋 같은 정보를 얻을 수 있음
 * 프로젝트 디버그 파일은 /debug 옵션을 주어서 빌드시 생성
  (VS에서는 고급 빌드 설정에서 따로 해제하지 않는 이상 기본으로 적용)

- 다른 스레드의 스택 궤적을 얻기 위해선 쓰레드를 생성자의 인수로 지정해야 함

 // 근데 public StackTrace(Thread targetThread, bool needFileInfo);
 // 이 생성자는 [Obsolete] 특성이 지정되서 쓰지 않는게 권장되고 있다
 // 22장에 다른 접근방식을 소개한다는데, 그걸 보고 수정

- Exception을 StackTrace의 생성자에 넘겨서 스택 궤적을 얻을 수 있음
 * Exception의 StackTrace는 StackTrace 객체가 아닌 String을 돌려줌
 * 예외를 로그에 기록한다면 문자열보다 StackTrace 객체가 더 유용할 것(IL Offset, ILDASM 활용)

- GetFrame: 특정 프레임 하나에 대한 StrackFrame
- GetFrames: 모든 프레임 열거

namespace Practice
{
    class Program
    {
        public static void Main(string[] arg)
        {
            FunctionA();
        }
 
        static void FunctionA()
        {            
            Console.WriteLine("FunctionA start...");
            FunctionB();
            Console.WriteLine("FunctionA end...");
        }
 
        static void FunctionB()
        {
            Console.WriteLine("FunctionB start...");
            FunctionC();
            Console.WriteLine("FunctionB end...");
        }
 
        static void FunctionC()
        {
            Console.WriteLine("FunctionC start...\n");
 
            // pdb 파일을 참조하는 StackTrace 인스턴스
            StackTrace st = new StackTrace(true);
 
            Console.WriteLine("    프레임 수: " + st.FrameCount);
            Console.WriteLine("현  재 메서드: " + st.GetFrame(0).GetMethod().Name);
            Console.WriteLine("호출한 메서드: " + st.GetFrame(1).GetMethod().Name);
            Console.WriteLine("진  입 메서드: " + st.GetFrame(st.FrameCount - 1).GetMethod().Name);
            Console.WriteLine();
 
            Console.WriteLine("-- 호출 스택 --");
            foreach (StackFrame sf in st.GetFrames())
            {
                Console.WriteLine(
                    "  파  일: " + sf.GetFileName() +
                    "      행: " + sf.GetFileLineNumber() +
                    "      열: " + sf.GetFileColumnNumber() +
                    "  오프셋: " + sf.GetILOffset() +
                    "  메서드: " + sf.GetMethod().Name);
            }
            Console.WriteLine();
 
            Console.WriteLine("FunctionC end...");
        }
    }
}

- GetILOffset: CIL(Common Intermediate Language, 전에는 Microsoft Intermediate Language, MSIL)에서의
               다음번 실행될 오프셋 위치
- GetNativeOffset: JIT 컴파일 코드에서의 다음번 실행될 오프셋 위치

- 행 번호(GetFileLineNumber)와 열 번호(GetFileColumnNumber)의 경우 보통 현재 실행의 지점의 것들
- CLR은 IL 오프셋으로부터 행 번호와 열 번호를 추론하는데, 
  디버그 모드와 코드, 최적화 상태에 따라 추론되는 위치가 달라질 수 있음
- ToString: 간단하게 필수적인 정보를 획득

반응형

'C#' 카테고리의 다른 글

[C#] Thread  (0) 2023.11.01
[C#] Stopwatch  (0) 2023.10.30
[C#] PerformanceCounter, PerformanceCounterCategory  (0) 2023.10.28
[C#] EventLog (Windows 이벤트 로그)  (0) 2023.10.26
[C#] Debugger  (0) 2023.10.22
[C#] Contract, Code Contracts(코드 계약)  (0) 2023.10.20
[C#] Debug, Trace  (0) 2023.10.18
[C#] WeakReference  (0) 2023.10.14