项目需要监测在Windows平台的崩溃情况,折腾了两天终于弄好了,记录一下。

1.捕获崩溃信息

接到这个需求,心想应用崩溃系统会收到信号,应该有相应的函数可以监听,上网搜索,果不其然函数

SetUnhandledExceptionFilter

便有此功能,用法也不复杂,在项目里实现之后发现监测不到【Debug/Release】~~~我勒个擦

搜索 SetUnhandledExceptionFilter无效 貌似蛮多人遇到这个问题的,参考几个博客的内容

尝试了几次依然还是捕获失败,遂放弃了此种方式。

搜索有没有相关的SDK可以使用,还好找到了CrashRpt库,接口简洁接入方便,官方提供的示例

CrashRpt: An Example of Using CrashRpt API

参照示例接入,发现确实可以捕获到崩溃(*^▽^*),而且捕获的信息参数里有崩溃的必要信息

但是来了,但是造了几个崩溃测试了几把,这几个参数一直为空~~我去~~

没办法只能上传崩溃堆栈了,幸好参数里有崩溃信息文件的地址

读取该文件,哎呀,崩溃时改文件还未写入,尼玛~~~看来要自己写崩溃信息文件了

参考两种Dump(崩溃日志)文件生成的方法及比较博文成功将崩溃信息写入文件,

2.信息上报给服务器

信息上报需要注意,可能由于还未上传程序便结束了,因此主线程最好短暂休眠,给上报线程预留时间

3.分析崩溃信息,定位崩溃原因

使用WinDbg工具【需下载Windows SDK】

打开WinDbg,依次进行下面操作:
File -> Symbol File Path -> 选择pdb文件存放路径。
File -> Image File Path -> 选择exe文件存放路径。
File -> Open Crash Dump -> 选择DMP文件存放路径。
最后会弹出WinDbg对崩溃文件的初步分析的结果,在下面的输入框中输入“!analyze -v”,意思是软件进行对崩溃文件进行分析,并显示出来,然后根据分析结果定位崩溃原因。

Debug->Stop Debugging停止当前分析

至此,Windows平台捕获C++崩溃,上报并分析定位崩溃原因的功能便完成了。

实现代码如下:


#include <iostream>
#include <stdio.h>
#include <tchar.h>
#include <string>
#include <stdlib.h>
#include <windows.h>#include <strsafe.h>
#pragma comment(lib,"DbgHelp.lib")#include "include/CrashRpt.h" void log(const std::string& str)
{std::cout << str.c_str() << std::endl;
}std::string StringWideCharToUtf8(const std::wstring& strWideChar)
{std::string ret;if (!strWideChar.empty()){int nNum = WideCharToMultiByte(CP_UTF8, 0, strWideChar.c_str(), -1, nullptr, 0, nullptr, FALSE);if (nNum){char* utf8String = new char[nNum + 1];utf8String[0] = 0;nNum = WideCharToMultiByte(CP_UTF8, 0, strWideChar.c_str(), -1, utf8String, nNum + 1, nullptr, FALSE);ret = utf8String;delete[] utf8String;}}return ret;
}//将崩溃信息写入文件
typedef BOOL(WINAPI* TKPGetModuleHandleEx)(DWORD dwFlags, LPCTSTR lpModuleName, HMODULE* phModule);
VOID createCrashDump(struct _EXCEPTION_POINTERS* pExceptionPointers, std::string& path)
{//收集信息HMODULE hModule;WCHAR szModuleName[MAX_PATH] = { 0 };TKPGetModuleHandleEx pFun = (TKPGetModuleHandleEx)GetProcAddress(GetModuleHandle(L"kernel32.dll"), "GetModuleHandleExW");if (!pFun) {return;}pFun(GET_MODULE_HANDLE_EX_FLAG_FROM_ADDRESS, (LPCWSTR)pExceptionPointers->ExceptionRecord->ExceptionAddress, &hModule);GetModuleFileName(hModule, szModuleName, ARRAYSIZE(szModuleName));//生成 mini crash dumpBOOL bMiniDumpSuccessful;WCHAR szPath[MAX_PATH];WCHAR szFileName[MAX_PATH];WCHAR* szAppName = L"DumpFile";WCHAR* szVersion = L"v1.0";DWORD dwBufferSize = MAX_PATH;HANDLE hDumpFile;SYSTEMTIME stLocalTime;MINIDUMP_EXCEPTION_INFORMATION ExpParam;GetLocalTime(&stLocalTime);GetTempPath(dwBufferSize, szPath);StringCchPrintf(szFileName, MAX_PATH, L"%s%s", szPath, szAppName);CreateDirectory(szFileName, NULL);StringCchPrintf(szFileName, MAX_PATH, L"%s%s//%s-%04d%02d%02d-%02d%02d%02d-%ld-%ld.dmp",szPath, szAppName, szVersion,stLocalTime.wYear, stLocalTime.wMonth, stLocalTime.wDay,stLocalTime.wHour, stLocalTime.wMinute, stLocalTime.wSecond,GetCurrentProcessId(), GetCurrentThreadId());hDumpFile = CreateFile(szFileName, GENERIC_READ | GENERIC_WRITE,FILE_SHARE_WRITE | FILE_SHARE_READ, 0, CREATE_ALWAYS, 0, 0);ExpParam.ThreadId = GetCurrentThreadId();ExpParam.ExceptionPointers = pExceptionPointers;ExpParam.ClientPointers = TRUE;MINIDUMP_TYPE MiniDumpWithDataSegs = (MINIDUMP_TYPE)(MiniDumpNormal| MiniDumpWithHandleData| MiniDumpWithUnloadedModules| MiniDumpWithIndirectlyReferencedMemory| MiniDumpScanMemory| MiniDumpWithProcessThreadData| MiniDumpWithThreadInfo);bMiniDumpSuccessful = MiniDumpWriteDump(GetCurrentProcess(), GetCurrentProcessId(),hDumpFile, MiniDumpWithDataSegs, &ExpParam, NULL, NULL);path = StringWideCharToUtf8(szFileName);return;
}//程序崩溃时CrashRpt库抛出的监听事件
int CALLBACK crashCallback(CR_CRASH_CALLBACK_INFO* pInfo)
{// The application has crashed!// Close the log file here// to ensure CrashRpt is able to include it into error reportstd::string filePath;createCrashDump(pInfo->pExceptionInfo->pexcptrs, filePath);unsigned len = 0;FILE* fp = fopen(filePath.c_str(), "rb");if (fp){fseek(fp, 0, SEEK_END);len = ftell(fp);fclose(fp);}//此处将数据上报服务器【子线程上报】//主线程暂时休眠1秒Sleep(1000);log("crash------");return CR_CB_CANCEL;
}int installCrashRpt()
{CR_INSTALL_INFO info;memset(&info, 0, sizeof(CR_INSTALL_INFO));info.cb = sizeof(CR_INSTALL_INFO);info.pszAppName = _T("Test");info.pszAppVersion = _T("1.0.0");info.pszEmailSubject = _T("Test Error Report");//info.uPriorities[CR_HTTP] = 3;  // 首先使用HTTP的方式发送错误报告info.uPriorities[CR_SMTP] = 2;  // 然后使用SMTP的方式发送错误报告  info.uPriorities[CR_SMAPI] = 1; //最后尝试使用SMAPI的方式发送错误报告    // 捕获所有能够捕获的异常, 使用HTTP二进制编码的方式传输info.dwFlags |= CR_INST_ALL_POSSIBLE_HANDLERS;info.dwFlags |= CR_INST_HTTP_BINARY_ENCODING;info.dwFlags |= CR_INST_APP_RESTART;info.dwFlags |= CR_INST_SEND_QUEUED_REPORTS;info.pszRestartCmdLine = _T("/restart");// 隐私策略URLinfo.pszPrivacyPolicyURL = _T("http://myapp.com/privacypolicy.html");int nResult = crInstall(&info);if (nResult != 0){TCHAR szErrorMsg[512] = _T("");crGetLastErrorMsg(szErrorMsg, 512);_tprintf_s(_T("%s\n"), szErrorMsg);log("crash rpt set falied");return 1;}log("crash rpt set success");crSetCrashCallback(crashCallback, NULL);
}int main(void)
{installCrashRpt();int* p=new int;delete p;*p = 5;system("pause");return 0;
}

附:接入CrashRpt除了头文件需要的文件列表

捕获崩溃需Release模式

参考资料:

应用程序异常处理与崩溃收集

SetUnhandledExceptionFilter拦不住的崩溃

分析两种Dump(崩溃日志)文件生成的方法及比较

vs2010 利用DMP文件、pdb文件查找release下的异常行号的方法

C++接入CrashRpt并上报分析崩溃信息相关推荐

  1. 安卓崩溃信息收集框架ACRA

    版权声明:本文为博主高远原创文章,转载请注明出处:http://blog.csdn.net/wgyscsf    https://blog.csdn.net/wgyscsf/article/detai ...

  2. 记录一次app崩溃信息调试

    收到了崩溃信息,如下 *** *** *** *** *** *** *** *** *** *** *** *** *** *** *** *** 2022-01-28 18:33:21.183 1 ...

  3. 如何在分析崩溃的边缘分析问题

    如何在分析崩溃的边缘分析问题 当一个人处理多个任务,不考虑并发和并行,只是单线程处理任务时: 我,一个默默无闻的程序员,既没有给世界带来更加丰富多彩的体验,也没有给公司带来质一般的超越,我就是一个默默 ...

  4. iOS 几种常用的 crash log 崩溃信息调试方法. (转载)

    前言:crash log 对 定位崩溃问题 ,并且不容易复现,尤其是及时对appstore 上正在运营的 app 的迭代改进来说 非常重要. 1 crash两种情况 1.1 测试环境下 追踪bug 1 ...

  5. Analyzing Crash Reports——分析崩溃报告之一

    以下文章翻译自: Analyzing Crash Reports Analyzing Crash Reports After you distribute your app for testing b ...

  6. windbg分析崩溃dmp

    首先我们收集了程序崩溃的dump文件,然后将dump文件拖拽到windbg下,然后依次如下命令: 1.设置符号路径:.sympath srv*C:\symbols*http://msdl.micros ...

  7. iOS 几种常用的 crash log 崩溃信息调试方法

    前言:crash log 对 定位崩溃问题 ,并且不容易复现,尤其是及时对appstore 上正在运营的 app 的迭代改进来说 非常重要. 1 crash两种情况 1.1 测试环境下 追踪bug 1 ...

  8. vs2012 map cod文件崩溃信息

    最近在做服务器,很是纠结崩溃信息获取,网上查了些资料,直指map文件信息分析 1.首先生成map cod 文件 直接上图 然后直接编译生成PokerPDKServer.map  和每一个cpp对已的T ...

  9. iOS-几种常用的 crash log 崩溃信息调试方法

    前言:crash log 对 定位崩溃问题 ,并且不容易复现,尤其是及时对appstore 上正在运营的 app 的迭代改进来说 非常重要. 1 crash两种情况 1.1 测试环境下 追踪bug 1 ...

最新文章

  1. 1.4亿围观!宝藏副教授火速走红:如果不喜欢我的研究方向,我可以改!
  2. Oracle导入导出dmp文件
  3. 企业做SEO优化哪些行为会被判定为作弊?
  4. Java IO流中 File文件对象与Properties类(四)
  5. Windows Server 2012 网络负载均衡
  6. Intel Realsense D435 Realsense View 错误 RT IC2 Config error
  7. Supervisor使用教程
  8. 搭建cacti监控平台
  9. idea messages中文乱码_2019.2版本IDEA控制台中文乱码尝试了很多方法都不行
  10. 20200501:力扣185周赛上
  11. 【译】ZFS最佳实践指南-Part2
  12. Dubbo视频教程--基础篇--第03节--ZooKeeper注册中心安装详细步骤(单节点)
  13. 126邮箱stmp服务器,免费邮箱
  14. POJ 1723(中位数+连续排列)
  15. vue-如何获取上一个路由地址
  16. 基于FPGA的PWM加减速控制实现
  17. EPSON RX8010SJ RTC 调试笔记之五, 时钟及日历解析
  18. Excel数据透视表经典教程六《报表布局》
  19. [转]ESMTP的三个认证方式: CRAM-MD5 PLAIN和LOGIN
  20. vue+elementui实现非常好看的博客、网站首页,网站模板

热门文章

  1. Can you answer these queries? HDU - 4027
  2. java 多线程下载 断点_Java 多线程断点下载文件
  3. 制造焦虑的医美平台,打碎医美行业的“信任之镜”
  4. spring boot多数据源动态切换, 多数据源事务管理
  5. 常见验证码的弱点与验证码识别
  6. 浅谈MSP430存储器——Flash和FRAM
  7. JAVA(2021-11-17)leetcode每日一题---- 最大单词长度乘积
  8. 你愿意被“甩”向火星吗?
  9. 新版chrome无法使用IDM下载
  10. [巩固C#] 一、特性是什么东东