• 优秀开源项目之四:CrashRptProbe,查询程序奔溃的利器


    1.背景:

      在开发人员进行项目开发和调试代码时,有一个非常困扰的问题,就是程序在调试运行过程中会莫名其妙地异常退出。由于导致异常退出的问题非常多,因此在面对这种无任何提示的异常退出时,开发人员会非常无奈。因为他需要考虑最近的那些更改有可能导致这个错误的发生,万不得已,可能就需要把代码回退到某个版本,然后去慢慢验证了。这当然是非常影响工作效率的。

      后来,项目经理前段时间介绍了一个新的库,用这个库可以非常准确地定位上一次奔溃的出错位置。这样开发人员便可以在奔溃的位置添加断点,进行调试。

      自从知道有这个工具后,我就爱不释手。从此,再也不怕遇到程序异常退出的情况了。因为你知道,那里有一个助手帮你监视着程序的一举一动,随时等待你的召唤。

      下面就介绍一下这个工具,它的名字叫:**CrashRptProbe。**Probe是探针的意思,顾名思义,就是探测程序奔溃并发送报告的一个工具。这个工具在Github上的地址为:https://github.com/bitshares/devshares/tree/master/CrashRpt

    2. CrashRptProbe的基本介绍:

      目前我是将这个库引入了VS2012开发C++的项目中,在其他开发工具和语言上还没有试过。

      这个工具是作为第三方库引入项目中的。它的地位就和之前引入的其他第三方库,如DCMTK, VTK, ITK, GTEST, OpenCV, log4cplus等一样。

      从Github上把这个包下载下来,并解压到项目中的thirdparty中即可。或者从以下的链接中下载这个包。

      具体的放置位置如下图所示: 

    由于需要把该工具引入到项目中。因此需要将它在放置在和本项目的应用程序的入口函数main.cpp的同级目录内。并且需要定义一个当系统奔溃时,奔溃报告的存放位置。因此,在main.cpp的同级目录下,创建两个文件:
    CrashHandler.h和CrashHandler.cpp。

    CrashHandler.h的代码为:

    [cpp] view plain copy
     
    1. #ifndef _DXCRASHHANDLER_H_  
    2. #define _DXCRASHHANDLER_H_  
    3.   
    4. #include <QString>  
    5. class DxCrashHandler  
    6. {  
    7. public:   
    8.     DxCrashHandler();  
    9.     ~DxCrashHandler();  
    10. private:  
    11.     QString AddAppPath(const QString relativepath);  
    12. };  
    13.   
    14. #endif // _DXCRASHHANDLER_H_  

    CrashHandler.cpp的代码为:

    [cpp] view plain copy
     
    1. #include "CrashRpt.h"  
    2. #include "DxCrashHandler.h"  
    3. #include <QApplication>  
    4. #include <QDir>  
    5. #include <QMainWindow>  
    6. #include <QMessageBox>  
    7.   
    8. QString DxCrashHandler::AddAppPath(const QString relativepath)  
    9. {  
    10.     QDir root(QCoreApplication::applicationDirPath());  
    11.     return QDir::cleanPath(root.absoluteFilePath(relativepath));  
    12. }  
    13. // Define the callback function that will be called on crash  
    14. int CALLBACK CrashCallback(CR_CRASH_CALLBACK_INFO* pInfo)  
    15. {    
    16.     // The application has crashed!  
    17.     if ( pInfo->nStage == CR_CB_STAGE_PREPARE )  
    18.     {  
    19.         // Close log file here when necessary  
    20.     }  
    21.     else //CR_CB_STAGE_FINISH  
    22.     {  
    23.         QMessageBox::critical(QApplication::activeWindow(), "FTT3D", "There is some critical error in the application. So it will be closed.  Please send error reports and related information to the administrators.  That will help us to improve the product.");  
    24.     }  
    25.     // Return CR_CB_DODEFAULT to generate error report  
    26.     return CR_CB_NOTIFY_NEXT_STAGE ; //CR_CB_DODEFAULT;  
    27. }  
    28.   
    29. DxCrashHandler::DxCrashHandler()  
    30. {  
    31.     // Install crash reporting  
    32.     CR_INSTALL_INFO info;  
    33.     memset(&info, 0, sizeof(CR_INSTALL_INFO));  
    34.     info.cb = sizeof(CR_INSTALL_INFO);    
    35.     info.pszAppName = "TestAPP"; // Define application name.  
    36.     info.pszAppVersion = "1.0"; // Define application version.  
    37.   
    38.     //Install all available exception handlers.  
    39.     info.dwFlags |= CR_INST_ALL_POSSIBLE_HANDLERS;   
    40.     info.dwFlags |= CR_INST_DONT_SEND_REPORT;  
    41.     info.dwFlags |= CR_INST_STORE_ZIP_ARCHIVES ;  
    42.     info.dwFlags |= CR_INST_AUTO_THREAD_HANDLERS ;  
    43.   
    44.     //Set the error reprot path  
    45.     char lpsReportPath[MAX_PATH];  
    46.     strcpy_s(lpsReportPath,   
    47.         (LPCTSTR)(AddAppPath("ErrorReport")).toLocal8Bit().data()  
    48.         );  
    49.     info.pszErrorReportSaveDir = lpsReportPath;  
    50.   
    51. //     Article effective minidumps recommand the MiniDumpWithPrivateReadWriteMemory. But it cause the dump file up to 50 MB.  
    52. //     So we use the MiniDumpWithIndirectlyReferencedMemory as alternative, which lost some information but ensure the  
    53. //     a reasonable dump size.  
    54.     // Not all flag will be used due to some callback not provided in crashrpt licrary. If more dump needed, we must modify the   
    55.     // crashrpt code about crashdump.  
    56.     info.uMiniDumpType  = (MINIDUMP_TYPE)( // MiniDumpWithPrivateReadWriteMemory |   
    57.         MiniDumpWithDataSegs |   
    58.         MiniDumpWithHandleData |  
    59.         // The following parameters are supported by 6.2 and later  
    60.         MiniDumpWithIndirectlyReferencedMemory |  
    61.         MiniDumpWithFullMemoryInfo |   
    62.         MiniDumpWithThreadInfo |   
    63.         MiniDumpWithUnloadedModules   
    64.         );   
    65.     int nResult = crInstall(&info);  
    66.     if(nResult!=0)  
    67.     {  
    68.         QMessageBox::warning(NULL, "TestApp", "Prepare error report handler failed!");  
    69.     }  
    70.     //      Set crash callback function  
    71.      crSetCrashCallback(CrashCallback, NULL);  
    72.     // Add the last application log   
    73.     crAddFile2(  
    74.         (LPCTSTR)(AddAppPath("TestApp.App.log")).toLocal8Bit().data(),   
    75.         "TestApp.app.log",   
    76.         ("Log file"),   
    77.         CR_AF_MAKE_FILE_COPY |CR_AF_MISSING_FILE_OK );  
    78.     // Take screenshot of the app window at the moment of crash  
    79.     crAddScreenshot2(CR_AS_MAIN_WINDOW|CR_AS_USE_JPEG_FORMAT, 95);  
    80. }  
    81.   
    82. DxCrashHandler::~DxCrashHandler()  
    83. {  
    84.     //Uninstall crash reporting  
    85. }  

    3. 在项目中引入Thirdparty - CrashRptProbe

    根据以上的步骤,将CrashRptProbe的输入奔溃报告的路径指定后,我们便可以将它引入项目中了。

    在项目的起始入口函数main.cpp中,需要实例化这个类的一个对象。

    [cpp] view plain copy
     
    1. int main(int argc, char *argv[])  
    2. {  
    3.     QApplication a(argc, argv);  
    4.   
    5.     // Initialize the crash handler  
    6.     DxCrashHandler crashhandler;  
    7.   
    8.     return 0;  
    9. }  

    之后,我们便可以在项目中进行测试了。


    以下是我的测试步骤,我在原来某一个文件调用一个指针的方法时,去掉了这个指针的new。因此,当程序运行到这里的时候,便会由于指针未初始化而发生奔溃。

    (1)当发生奔溃后,不用担心。这时在Bin目录下面会自动生成一个名字为ErrorReport的文件夹,如图所示。

    (2)然后打开这个文件,会出现一些压缩文件和文件夹。根据时间排序,找到最近生成的一个文件夹并打开,便可以看到本次奔溃的报告文件,后缀名为dmp文件。 

    (3)点击右键,选择VS2012打开该dmp文件,可以看到它会加载程序奔溃时的部分程序并打开。此时,在界面的右上部分的Actions下面,会有一个绿色的按钮,名称为 Debug with Native Only.

    (4)点击这个绿色按钮后,会弹出一个异常信息提示框,如图所示。 
    然后点击这个提示对话框上的Break按钮,则可以看到它已经帮我们定位到了该源代码的第97行。因为,我之前测试时并没有去New这个m_pVolume的指针,因此当程序运行到这里时便会奔溃。

    可见,这个工具可以非常高效地帮我们记录程序出现异常的位置,提高我们debug代码和查找异常的效率。

     

    参考链接:

    CrashRptProbe在Github上的地址:

    https://github.com/bitshares/devshares/tree/master/CrashRpt https://groups.google.com/forum/#!msg/crashrpt/UEnzFEiXyAo/e3M_butCBQAJ

    http://blog.csdn.net/caoshangpa/article/details/76575920

  • 相关阅读:
    jquery操作select
    EL表达式
    八大排序算法之希尔排序
    八大排序算法之堆排序
    八大排序算法之归并排序
    yield与send实现协程操作
    详解生成器、迭代器
    类相关知识
    python装饰器大详解
    详解python之反射机制
  • 原文地址:https://www.cnblogs.com/findumars/p/7694222.html
Copyright © 2020-2023  润新知