StackTrace 클래스
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 클래스
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 |