بارها براتون پیش اومده که کلاینت کرش می کنه برای رفع این کرش باید نقطه کرش تو دیباگرتون مشخص باشه که به خطای نقطه موردنظر پی ببرید.
یکی از راههای که وجود داره استفاده از لاگ چرخشی بر روی هارد دیسک هستس که تمامی هات اسپات مستعد یا ورودی و خروجی توابع مستعد رو لاگ بزنیم که بعد این فایل dump را بررسی کنیم ببینم کلاینت تو کدام تابع متوقف شده البته همانطوری که می دونید تو این حالت وضعیت حافظه در اختیارتون نیست که دقیقا متوجه بشید تو چه شرایطی همچنین مشکلی در آن نقطه خاص بوجود آمده
راه حل دیگر ذخیره سازی dump حافظه در صورت کرش به صورت minidump روی کلاینت هستش البته این کار تو پلتفرم های مختلف فرق داره که هر پلت فرمی API متفاوتی برای اینکار در نظر گرفته شده .جهت استفاده از راه حل کرس پلتفرم شرکت گوگل فریم ورکی به نام BreakPad طراحی کرده که فایل minidump با ساختار minidump ویژوال استدیو براتون میسازه که این فایل تو ویندوز با دیباگر vs و windbg سازگار هستش برای اینکار ابتدا Breakpad را clone کنید و سپس بیلدش کنید من این کار را با vcpkg نجام دادم.حالا برای گزارش گیری از کرش کلاینت به مراحل زیر نیاز دارید.
1-تو properties->linker->debugger->genrate debug info را فعال کنید با اینکار فایل .pdb ساخته میشه که این فایل در مرحله بعد بهش نیاز داریم.
2-حالا باید یه کلاس crashhandler بسازید که به صورت زیر عمل کنید.
//CrashHandler.h
#pragma once
#pragma once
#include <QtCore/QString>
namespace Atomix
{
class CrashHandlerPrivate;
class CrashHandler
{
public:
static CrashHandler* instance();
void Init(const QString& reportPath);
void setReportCrashesToSystem(bool report);
bool writeMinidump();
private:
CrashHandler();
~CrashHandler();
Q_DISABLE_COPY(CrashHandler)
CrashHandlerPrivate* d;
};
}
//CrashHandler.cpp
#include "CrashHandler.h"
#include <QtCore/QDir>
#include <QtCore/QProcess>
#include <QtCore/QCoreApplication>
#include <QString>
#if defined(Q_OS_MAC)
#include "client/mac/handler/exception_handler.h"
#elif defined(Q_OS_LINUX)
#include "client/linux/handler/exception_handler.h"
#elif defined(Q_OS_WIN32)
#include "client/windows/handler/exception_handler.h"
#endif
namespace Atomix
{
/************************************************************************/
/* CrashHandlerPrivate */
/************************************************************************/
class CrashHandlerPrivate
{
public:
CrashHandlerPrivate()
{
pHandler = NULL;
}
~CrashHandlerPrivate()
{
delete pHandler;
}
void InitCrashHandler(const QString& dumpPath);
static google_breakpad::ExceptionHandler* pHandler;
static bool bReportCrashesToSystem;
};
google_breakpad::ExceptionHandler* CrashHandlerPrivate::pHandler = NULL;
bool CrashHandlerPrivate::bReportCrashesToSystem = false;
/************************************************************************/
/* DumpCallback */
/************************************************************************/
#if defined(Q_OS_WIN32)
bool DumpCallback(const wchar_t* _dump_dir, const wchar_t* _minidump_id, void* context, EXCEPTION_POINTERS* exinfo, MDRawAssertionInfo* assertion, bool success)
#elif defined(Q_OS_LINUX)
bool DumpCallback(const google_breakpad::MinidumpDescriptor &md, void *context, bool success)
#elif defined(Q_OS_MAC)
bool DumpCallback(const char* _dump_dir, const char* _minidump_id, void *context, bool success)
#endif
{
Q_UNUSED(context);
#if defined(Q_OS_WIN32)
Q_UNUSED(_dump_dir);
Q_UNUSED(_minidump_id);
Q_UNUSED(assertion);
Q_UNUSED(exinfo);
#endif
qDebug("BreakpadQt crash");
/*
NO STACK USE, NO HEAP USE THERE !!!
Creating QString's, using qDebug, etc. - everything is crash-unfriendly.
*/
return CrashHandlerPrivate::bReportCrashesToSystem ? success : true;
}
void CrashHandlerPrivate::InitCrashHandler(const QString& dumpPath)
{
if (pHandler != NULL)
return;
#if defined(Q_OS_WIN32)
std::wstring pathAsStr = (const wchar_t*)dumpPath.utf16();
pHandler = new google_breakpad::ExceptionHandler(
pathAsStr,
/*FilterCallback*/ 0,
DumpCallback,
/*context*/
0,
true
);
#elif defined(Q_OS_LINUX)
std::string pathAsStr = dumpPath.toStdString();
google_breakpad::MinidumpDescriptor md(pathAsStr);
pHandler = new google_breakpad::ExceptionHandler(
md,
/*FilterCallback*/ 0,
DumpCallback,
/*context*/ 0,
true,
-1
);
#elif defined(Q_OS_MAC)
std::string pathAsStr = dumpPath.toStdString();
pHandler = new google_breakpad::ExceptionHandler(
pathAsStr,
/*FilterCallback*/ 0,
DumpCallback,
/*context*/
0,
true,
NULL
);
#endif
}
/************************************************************************/
/* CrashHandler */
/************************************************************************/
CrashHandler* CrashHandler::instance()
{
static CrashHandler globalHandler;
return &globalHandler;
}
CrashHandler::CrashHandler()
{
d = new CrashHandlerPrivate();
}
CrashHandler::~CrashHandler()
{
delete d;
}
void CrashHandler::setReportCrashesToSystem(bool report)
{
d->bReportCrashesToSystem = report;
}
bool CrashHandler::writeMinidump()
{
bool res = d->pHandler->WriteMinidump();
if (res) {
qDebug("BreakpadQt: writeMinidump() successed.");
}
else {
qWarning("BreakpadQt: writeMinidump() failed.");
}
return res;
}
void CrashHandler::Init(const QString& reportPath)
{
d->InitCrashHandler(reportPath);
}
}