تهیه dump file در هنگام برخورد خطا در کلاینت - هفت خط کد انجمن پرسش و پاسخ برنامه نویسی

تهیه dump file در هنگام برخورد خطا در کلاینت

0 امتیاز

سلام به همگی.

من از این آموزش استفاده کردم برای تهیه dump فایل  تست کردم درست هم کار هم می کنه به قول @فرهاد شیری کاشکی به QT وابسته نبود آیا راه حل c++ ی سراغ دارید؟

سوال شده مرداد 21, 1399  بوسیله ی COLD (امتیاز 200)   4 28 37

2 پاسخ

+3 امتیاز
 
بهترین پاسخ

سلام. اون نسخه ای از breakpad که من در اون پست توضیح دادم وابسته به QT بود ولی در کل نسخه رسمی وابسته به Qt  نیست .یک بار نسخه اصلی را براتون توضیح میدم شاید بدردتون خورد:

 

۱- از گیت هاب نسخه رسمی breakpad را دانلود کنید.

 

۲- از گیت هاب gyp  (Generate Your Projects) را دانلود کنید.

 

۳- پایتون هم روی سیستم تون نصب باشه .

 

۴- از این طریق breakpad را جنریت کنید

 

tools\gyp\gyp.bat --no-circular-check client\windows\breakpad_client.gyp

 

۵- پروژه ها را بیلد کنید.

 

۶- برای dump‌کردن شما به ۳ کتابخانه زیر نیاز دارید:

 

  • common.lib
  • crash_generation_client.lib
  • exception_handler.lib

 

۷- کد زیر را به پروژه خودتون اضاففه کنید:

#include "client/windows/handler/exception_handler.h"

int main()
{
    google_breakpad::ExceptionHandler *pCrashHandel = 
        new google_breakpad::ExceptionHandler(
        L".", 
        NULL,
        NULL,
        NULL,
        google_breakpad::ExceptionHandler::HANDLER_ALL,
        NULL);
    
    char *pBuf = NULL;
    *pBuf = 'a';
    return 0;
}

 

اگر هم قصد دارید به صورت پیشرفته تر dump را مدیریت کنید از مثال زیر استفاده کنید:

#include "client/windows/handler/exception_handler.h"

// Minidump with stacks, PEB, TEB, and unloaded module list.
const MINIDUMP_TYPE kSmallDumpType = static_cast<MINIDUMP_TYPE>(
    MiniDumpWithProcessThreadData |  // Get PEB and TEB.
    MiniDumpWithUnloadedModules);  // Get unloaded modules when available.

// Minidump with all of the above, plus memory referenced from stack.
const MINIDUMP_TYPE kLargerDumpType = static_cast<MINIDUMP_TYPE>(
    MiniDumpWithProcessThreadData |  // Get PEB and TEB.
    MiniDumpWithUnloadedModules |  // Get unloaded modules when available.
    MiniDumpWithIndirectlyReferencedMemory);  // Get memory referenced by stack.

// Large dump with all process memory.
const MINIDUMP_TYPE kFullDumpType = static_cast<MINIDUMP_TYPE>(
    MiniDumpWithFullMemory |  // Full memory from process.
    MiniDumpWithProcessThreadData |  // Get PEB and TEB.
    MiniDumpWithHandleData |  // Get all handle information.
    MiniDumpWithUnloadedModules);  // Get unloaded modules when available.
    
static google_breakpad:Exception *sg_pCrash = NULL;
static std::string sg_strDumpPath = "";


bool FilterCallback(void *context,
                    EXCEPTION_POINTERS *exinfo,
                    MDRawAssertionInfo *assertion)
{
    if(CFileUtil::createMultiDir(sg_strDumpPath))
    {
        return false;
    }
    
    return true;
}


bool installBreakpad()
{
    enum {BUF_LEN = 1024};
    char szBuf[BUF_LEN];
    memset(szBuf,0,sizeof(szBuf));
    GetModuleFileNameA(NULL,szBuf,BUF_LEN);
    
    boost::filesystem::path objPath(szBuf);
    std::string strFileName = objPath.stem().string();
    objPath.remove_filename();
    
    objPath /= "../../minidump";
    objPath /= strFileName;
    
    sg_strDumpPath = objPath.string();
    std::string strCodePage = boost::locale::util::get_system_locale();
    std::locale loc = boost::locale::generator().generate(strCodePage);
    std::wstring wstrPath = boost::locale::conv::to_utf<wchar_t>(sg_strDumpPath,loc);
    
    sg_pCrash = new google_breakpad::ExceptionHandler(wstrPath, 
                                                      FilterCallback,
                                                      NULL,
                                                      NULL,
                                                      google_breakpad::ExceptionHandler::HANDLER_ALL,
                                                      kFullDumpType,
                                                      (HANDLE)NULL,
                                                      NULL);
        
    return (sg_pCrash != NULL);
}

bool uninstallBreakpad()
{
    if(sg_pCrash != NULL)
    {
        delete sg_pCrash;
        sg_pCrash = NULL;
    }
    
    return true;
}
    
int main()
{
    installBreakpad();
    
    char *pBuf = NULL;
    *pBuf = 'a';
    
    uninstallBreakpad();
    return 0;
}

 

در هر دو کد خطای زیر هم قرار داده شده تا بتونید به راحتی تستش هم کنید:


    char *pBuf = NULL;
    *pBuf = 'a';

 

یادتون باشه اگر قرار dump فایل در فلدری ذخیره بشه اون فلدر را باید خودتون بسازید.

 

پس از برخورد با خطا در فلدر موردنظر dump فایل ایجاد میشه که می تونید در file->open در ویژوال استدیو بازش کنید و سپس با کلید play با عنوان debug with native only‌اجراش کنید و خطی که خطا در آن ایجاد شده ظاهر خواهد شد.

 

فقط  دو نکته هست که باید رعایت کنید

  • پروژه در کلاینت و سرور باید کاملا یکسان باشه اینطور نباشه که شما در سمت سرور تغییرات بدید بعد انتظار داشته باشید dump مربوط به کلاینت کار کنه .
  •  مسیر پروژه ها را در کلاینت و سرور یکسان در نظر بگیرید.
پاسخ داده شده مرداد 25, 1399 بوسیله ی مصطفی ساتکی (امتیاز 21,998)   24 34 75
ویرایش شده مرداد 25, 1399 بوسیله ی مصطفی ساتکی
+1 امتیاز
معمولا فریم ورک استانداردی برای تهیه snapshot of memory که معمولا به صورت dump فایل هستند، در خود زبان سی پلاس پلاس وجود ندارد

ولی ابزارهای فوق العاده ای مانند windbg, ollydbg,dbgView وجود دارند که می توانید یک باینری را دیباگ کنید، وهمچنین از حافظه اسنپ شات تهیه کنید البته ابزارهای استاتیک هم برای زمان توسعه وجود دارند مانند c++Check , C++Test و اگر هم از دیباگرهای ویژوال استودیو ویا اکلیپس استفاده کنید امکانات خیلی خوبی در اختیارتون قرار میذارن، مخصوصا اگر در لینوکس کد میزنید اکلیپس فوق العاده کار آمد هستش.

اگر هم دنبال کتابخانه های استاتیک در زمان توسعه هستید که نیازی به نصب ابزارهای که در بالا اشاره شده، دارید می توانید در لینوکس از ابزار valgrind استفاده کنید برای تهیه نقشه بیتی از حافظه و اگر هم در ویندوز کد میزنید که ویژوال استودیو دیباگر مخصوصا نسخه های 2012 به بالا به قدری قدرتمند هست که معمولا نیازی به هیچ کتابخانه جداگانه در زمان توسعه نخواهید داشت.
پاسخ داده شده مرداد 22, 1399 بوسیله ی فرهاد شیری (امتیاز 97)   1 3
...