MFC를 사용하여 프로그램을 개발하여 배포한 후 현장에서 문제가 발생하는 경우가 있다. 이때개발자는 프로그램을 디버깅을 해볼 수 있는 상황이 못된다. 이럴 때를 대비한 한가지 팁을 소개드립니다.
xCrash Report를 사용하면 개발프로그램이 Runtime중 사망시 사망직전 호출 스택과 시스템의 상태정보를 Log로 기록하여 분석할 수 있게 해줍니다.. 참 좋군요~
사용법은 아래와 같습니다.
1) Lib를 선언
#pragma comment(lib, "dXCrashRpt.lib")
2) App의 InitInstance에서 소스추가
BOOL CMyApp::InitInstance()
{
// gdiplsu start
Gdiplus::GdiplusStartupInput gdiplusStartupInput;
if(Gdiplus::GdiplusStartup(&gdiplusToken, &gdiplusStartupInput, NULL) != Gdiplus::Ok)
{
AfxMessageBox(_T("Error : Failed to initialize GDI+ library!"));
return FALSE;
}
// 응용 프로그램 매니페스트가 ComCtl32.dll 버전 6 이상을 사용하여 비주얼 스타일을
// 사용하도록 지정하는 경우, Windows XP 상에서 반드시 InitCommonControlsEx()가 필요합니다.
// InitCommonControlsEx()를 사용하지 않으면 창을 만들 수 없습니다.
INITCOMMONCONTROLSEX InitCtrls;
InitCtrls.dwSize = sizeof(InitCtrls);
// 응용 프로그램에서 사용할 모든 공용 컨트롤 클래스를 포함하도록
// 이 항목을 설정하십시오.
InitCtrls.dwICC = ICC_WIN95_CLASSES;
InitCommonControlsEx(&InitCtrls);
CWinApp::InitInstance();
if (!AfxSocketInit())
{
AfxMessageBox(IDP_SOCKETS_INIT_FAILED);
return FALSE;
}
// OLE 라이브러리를 초기화합니다.
if (!AfxOleInit())
{
AfxMessageBox(IDP_OLE_INIT_FAILED);
return FALSE;
}
AfxEnableControlContainer();
// Use Crash Report
::InstallXCrash(); // ß 요기에 사용을 선언합니다.
EnableTaskbarInteraction(FALSE);
// RichEdit 컨트롤을 사용하려면 AfxInitRichEdit2()가 있어야 합니다.
// AfxInitRichEdit2();
// 표준 초기화
// 이들 기능을 사용하지 않고 최종 실행 파일의 크기를 줄이려면
// 아래에서 필요 없는 특정 초기화
// 루틴을 제거해야 합니다.
// 해당 설정이 저장된 레지스트리 키를 변경하십시오.
// TODO: 이 문자열을 회사 또는 조직의 이름과 같은
// 적절한 내용으로 수정해야 합니다.
SetRegistryKey(_T("로컬 응용 프로그램 마법사에서 생성된 응용 프로그램"));
LoadStdProfileSettings(0); // MRU를 포함하여 표준 INI 파일 옵션을 로드합니다.
// 응용 프로그램의 문서 템플릿을 등록합니다. 문서 템플릿은
// 문서, 프레임 창 및 뷰 사이의 연결 역할을 합니다.
CSingleDocTemplate* pDocTemplate;
pDocTemplate = new CSingleDocTemplate(
IDR_MAINFRAME,
RUNTIME_CLASS(CMyDoc),
RUNTIME_CLASS(CMainFrame), // 주 SDI 프레임 창입니다.
RUNTIME_CLASS(CMyView));
if (!pDocTemplate)
return FALSE;
AddDocTemplate(pDocTemplate);
// 표준 셸 명령, DDE, 파일 열기에 대한 명령줄을 구문 분석합니다.
CCommandLineInfo cmdInfo;
ParseCommandLine(cmdInfo);
// 명령줄에 지정된 명령을 디스패치합니다.
// 응용 프로그램이 /RegServer, /Register, /Unregserver 또는 /Unregister로 시작된 경우 FALSE를 반환합니다.
if (!ProcessShellCommand(cmdInfo))
return FALSE;
// 창 하나만 초기화되었으므로 이를 표시하고 업데이트합니다.
m_pMainWnd->ShowWindow(SW_SHOW);
m_pMainWnd->UpdateWindow();
// 접미사가 있을 경우에만 DragAcceptFiles를 호출합니다.
// SDI 응용 프로그램에서는 ProcessShellCommand 후에 이러한 호출이 발생해야 합니다.
// Init all manager
CMainFrame* pMainFrame = (CMainFrame*)AfxGetMainWnd();
CMyDoc* pDoc = (CMyDoc*)pMainFrame->GetActiveDocument();
CMyView* pView = (CMyView*)pMainFrame->GetActiveView();
return TRUE;
}
3) 실행파일 폴더에 dll복사
dXCrashRpt.dll를 프로그램 실행 폴더에 복사
4) ExceptionHandler.h 헤더를 App 헤더에 선언(솔직히 이건 필요한지는 모르겠음)
#include "ExceptionHandler.h"
5) XCrashRpt.exe를 실행프로그램 위치에 복사한다.
이렇게 작업을 완료하였다면 프로그램 배포 후 문제가 발생했을 경우에 해당 프로그램이 있는 폴더에 ERRORLOG.txt가 생성되게 됩니다. 그럼 이 파일을 분석하시면 되겠죠~~
ERRORLOG의 내부에는 프로그램에 문제가 발생한 시점의 Callstack정보가 기록되어있습니다.
아래처럼요~~
출처 : 반사마의 낙서장
'Programing > Visual C++/MFC' 카테고리의 다른 글
자료형의 크기 및 범위 (0) | 2016.03.23 |
---|---|
DebugView 사용법 (0) | 2016.03.11 |
OnCtlColor(Dialog Control 에 색깔 입히기) (0) | 2014.05.08 |