9.오류 덤프 시스템 구축하기 튜토리얼

1. DbgHelp 라이브러리 설치

2. DbgHelp 라이브러리 설치

3. 덤프 서버 제작 예제

#include "../../../include/ProudNetServer.h"
#include "../../../include/DumpServer.h"
#include "MyDumpServer.h"

class CMyDumpServer : public IDumpServerDelegate
{
    ...
    virtual void OnStartServer(CStartServerParameter &refParam) override;
    String GetDumpFilePath(HostID clientEnid, const Proud::AddrPort& clientAddr, CPnTime dumpTime) override;
    void Run();
}

void main(int argc, char* argv[])
{
    CMyDumpServer srv;
    srv.Run();
}

4. 덤프 클라이언트 제작 예제

주의사항 :

• 스마트폰을 포함하는 모바일 환경에서의 덤프 클라이언트는 지원하지 않습니다.

• Proud.CMiniDumpParameter를 사용하여 반드시 덤프시스템을 초기화 해야합니다.

• 유니코드 프로그래밍 모델의 경우 main 함수의 와이드 문자 버전을 정의할 수 있는데, wmain 함수에 대한 argv 및 envp 매개 변수는 wchar_t* 형식을 사용해야 합니다.

• MiniDumpAction_AlarmCrash, MiniDumpAction_DoNothing 의 경우 분기처리 이후 반드시 return을 호출하여 프로그램을 종료시켜주어야 합니다. 그렇지 않으면 무한루프에 빠질 수 있습니다.

크래쉬된 프로그램이 서버에 오류 데이터를 보내서 서버에서 그것을 취합하는 과정의 예제 프로그램입니다.

본 예제 프로그램에 대한 상세한 소개는 Nettention 홈페이지의 시연 동영상 (http://www.nettention.com/ko/sample.aspx) 을 참고하십시오.

소스 파일은 <설치 폴더>/Sample/SimpleMiniDump을 참고하십시오.

#include "stdafx.h"
#include <atlpath.h>
#include "../../include/MiniDumper.h"
#include "../../include/DumpCommon.h"

using namespace Proud;

const int _MAX_PATH2 = 8192;
#define _COUNTOF(array) (sizeof(array)/sizeof(array[0]))

void GetDumpFilePath(LPWSTR output)
{
    WCHAR path[_MAX_PATH2];
    WCHAR drive[_MAX_PATH2];
    WCHAR dir[_MAX_PATH2];
    WCHAR fname[_MAX_PATH2];
    WCHAR ext[_MAX_PATH2];
    WCHAR module_file_name[_MAX_PATH2];
    
    GetModuleFileNameW(NULL, module_file_name, _COUNTOF(module_file_name));
    _tsplitpath_s(module_file_name, drive, _MAX_PATH2, dir, _MAX_PATH2, fname, _MAX_PATH2, ext, _MAX_PATH2);
    _tmakepath_s(path, _MAX_PATH2, drive, dir, L"", L"");
    wsprintf(output, L"%s%s.DMP", path, fname);
};

void AccessViolation()
{
    int* a = 0;
    *a = 1;
}

// void wmain(int argc, wchar_t* argv[])
int main(int argc, char* argv[])
{
    int nRetCode = 0;
    int *data = 0;
    int menu = 0;
    
    WCHAR dumpFileName[_MAX_PATH2] = { 0, };
    GetDumpFilePath(dumpFileName);
    
    CMiniDumpParameter parameter;
    parameter.m_dumpFileName = dumpFileName;
    parameter.m_miniDumpType = SmallMiniDumpType;
    
    switch (CMiniDumper::Instance().Startup(parameter))
    {
    case MiniDumpAction_AlarmCrash:
        // 오류 발생으로 새로운 프로세스에서 덤프 파일을 생성한 후, 이 값이 return이 됩니다.
        // 생성된 덤프 파일을 메일로 보내거나 에러 창을 보이는 등 유저가 덤프 파일 생성 후, 처리해야할 작업을 처리해주시면 됩니다.

        // A dump file is created at a new process due to error occurrence and then this value will be returned.
        // After a user create a dump file, do works that need to be done such as sending a created dump file by email or showing an error window.

        // 因出现错误,在新的process中生成转储文件后该值将被返还。
        // 将生成的转储文件以邮件的形式发送,或可以看到 Error对话框的用户生成转存文件后,处理应处理的事即可

        // エラー発生により新しいプロセスからダンプファイルを生成した後、この値がreturnされます。
        // 生成されたダンプファイルをメールで送ったり、エラーメッセージが提示されるなどユーザーがダンプファイル生成後、処理すべきの作業をしてください。
        ...
        return nRetCode;

    case MiniDumpAction_DoNothing:
        // 유저 호출로 새로운 프로세스에서 덤프 파일을 생성한 후, 이 값이 반환됩니다.
        // 이 경우에는 아무것도 하지 말아야합니다.

        // After creating a dump file at a new process by calling a user, this value will be returned.
        // In this case, you should not do anything.

        // 因用户呼叫,在新的process中生成转储文件后,该值将被返还。
        // 在这种情况,不要做任何事情。.

        // ユーザー呼び出しにより新しいプロセスからダンプファイルを生成した後、この値が返還されます。
        // この場合何もしないでください。
        ...
        return nRetCode;

    default:
        // MiniDumpAction_None
        // 일반적으로 앱 실행 시, 이 값이 반환됩니다.
        // 여기서는 일반적으로 처리해야할 일을 처리해주시면 됩니다.

        // When executing apps, this value will be returned.
        // In this case, do works that generally need to be done.

        // 一般运行App时,该值将被返还。
        //在这里处理一般应处理的事情即可。

        // 一般的にアプリ実行後、この値が返還されます。
        // ここでは一般的に処理すべきの事を処理してください。
        ...
        break;
    }

    while (1)
    {
        puts("MENU: 1. Access Violation('a')");
        printf("> ");

        menu = getchar();

        switch (menu)
        {
        case 'a':
            AccessViolation();
            break;
        default:
            break;
        }
    }
    return 0;
}