본문 바로가기

C#

덤프 파일 사용 방벙(.pdb 디버깅)

728x90

프로그램이 죽을 경우 덤프 파일 만들기

1. 솔루션 탐색기 - 프로젝트 우 클릭 - 추가 - 기존 항목 - MinidumpHelp.cs 추가

  • dbghelp.dll 파일은 윈도우에 기본적으로 설치돼있지만 배포할 컴퓨터에 없는 경우 실행 파일과 함께 배포

MinidumpHelp.zip
0.00MB

 

2. 컴퓨터의 운영체제와 동일한 솔루션 플랫폼으로 반드시 변경

  • 솔루션 플랫폼이 없을 경우 : 구성 관리자 - 활성 솔루션 플랫폼 - 새로 만들기
  • 64bit 운영체제의 경우 솔루션 플랫폼을 x64로 변경하여 빌드
  • Any CPU 불가

 

3. 소스

//Program.cs에 추가
namespace WindowsFormsApplication1
{
    static class Program
    {
        //이벤트 클래스(UI 예외)
        static void exceptionDump(object sender, System.Threading.ThreadExceptionEventArgs args)
        {
            //Exception e = args.Exception;
            //Console.WriteLine("errMsg: " + e.Message);
            //Console.WriteLine("errPos: " + e.TargetSite);

            //덤프 파일 경로 설정(MinidumpHelp.cs 에서도 수정)
            //MinidumpHelp.Minidump.install_self_mini_dump(Application.StartupPath);

            MinidumpHelp.Minidump.install_self_mini_dump();
        }

		//이벤트 클래스(처리되지 않은 예외)
		private static void CurrentDomain_UnhandledException(object sender, UnhandledExceptionEventArgs e)
		{
            //Exception e = args.Exception;
            //Console.WriteLine("errMsg: " + e.Message);
            //Console.WriteLine("errPos: " + e.TargetSite);

            //덤프 파일 경로 설정(MinidumpHelp.cs 에서도 수정)
            //MinidumpHelp.Minidump.install_self_mini_dump(Application.StartupPath);

            MinidumpHelp.Minidump.install_self_mini_dump();
		}

        /// <summary>
        /// The main entry point for the application.
        /// </summary>
        [STAThread]
        static void Main()
        {
            //이벤트 추가
            Application.ThreadException += new System.Threading.ThreadExceptionEventHandler(exceptionDump);

            Application.SetUnhandledExceptionMode(UnhandledExceptionMode.CatchException);
            AppDomain.CurrentDomain.UnhandledException += new UnhandledExceptionEventHandler(CurrentDomain_UnhandledException);


            Application.EnableVisualStyles();
            Application.SetCompatibleTextRenderingDefault(false);
            Application.Run(new Form1());
        }
    }
}

 

4. 임의의 지점에 버그를 발생시켜 테스트

//강제 크래쉬(프로그램이 종료됨)
string[] p = new string[1];
p[2] = "a";

 

5. 크래쉬가 발생하면 실행 파일 위치에 .dmp 파일이 생성됨

  • 파일명 : 년.월.일.시.분.초.dmp

6. 추후 배포 시 .exe 파일만 배포해도 되지만 덤프 파일을 받아 디버깅 시 반드시 같이 만든 .pdb 파일이 필요

  • 배포할 때는 프로젝트를 비롯해 .exe와 .pdb 파일을 별도로 관리해야 함(.pdb 경로 동일)
  • 배포 시 Debug와 Release 모드 상관 없음

덤프 파일 사용하기(.pdb 디버깅)

1. 크래쉬가 발생하여 생성된 덤프 파일을 실행

2. '관리 전용(으)로 디버그' 클릭

 

3. 크래쉬가 발생한 부분으로 화면이 전환

  • 반드시 덤프 파일을 생성했던 .exe 파일과 같이 빌드 되었던 .pdb 파일이 필요
  • 빌드 했던 프로젝트의 소스가 변경된 경우 크래쉬가 발생한 부분을 제대로 알 수 없음

+

.exe를 만들었을 당시와 프로젝트 폴더 이름이나 경로가 다른 경우

변경된 프로젝트 소스의 경로를 직접 설정

- 연결하는 창이 안 뜰 경우 호출 스택에서 노란 화살표가 가리키는 줄을 클릭하여 경로를 설정

프로그램이 죽었는데 덤프 파일이 안 생긴 경우

스택 오버 플로우로 죽은 경우 예외 처리 추가

typedef struct _MinidumpInfo
{
    DWORD threadId;    ///< crash가 발생한 threadId
    EXCEPTION_POINTERS* pException;    ///< 예외 포인터
} MinidumpInfo, *PMinidumpInfo;
 
int ExceptionHandler(EXCEPTION_POINTERS* pException)
{
    if (pException->ExceptionRecord->ExceptionCode == EXCEPTION_STACK_OVERFLOW)
    {
        MinidumpInfo info;
        info.threadId = ::GetCurrentThreadId();
        info.pException = pException;
        // 덤프 찍기용 쓰레드 하나 생성해 주고
        HANDLE hThread = (HANDLE)_beginthreadex(0, THEAD_STACK_SIZE(대략 2메가), CreateMiniDump, &info, 0, NULL);
        // 생성 쓰레드가 덤프 끝날 때까지 기다린다
        WaitForSingleObject(hThread, INFINITE);
        CloseHandle(hThread);
    }
    else
    {
        /// 스택 오버플로우가 없는 일반적인 경우의 덤프 처리
    }
    return EXCEPTION_EXECUTE_HANDLER;
}

.pdb 파일 생성이 안 될 경우

1. 솔루션 탐색기 - 프로젝트 우 클릭 - 속성

2. 속성 페이지 - 구성 속성 - 링커 - 디버깅

3. 구성에서 Debug/Release 모드 둘 다 프로그램 데이터 베이스 파일 생성이 돼있는지 확인

- Debug/Release 모드에 상관없이 .pdb 파일이 있으면 덤프 파일 사용 가능

 

[출처]

https://blog.naver.com/wlvkddlwkd/222249774926

https://m.blog.naver.com/wlvkddlwkd/222263566463

728x90