一、前言
客户端有bug很正常,但是bug导致程序崩溃,就必须重视起来,所以为了更好的定位崩溃原因,需要做一些特殊处理。因为只做过linux和window平台,所以下面只针对这两个平台列出处理办法,mac平台的恕无能为力了。
二、 win下崩溃
window下程序crash,可以产生dump文件,然后使用windbg工具来显示dump文件中的崩溃,从而定位问题。下面就qt来分析下,具体如何利用dump分析问题。
- 让release版本也能生成dump文件
在每个.pro文件中加上:
win32:{
QMAKE_LFLAGS_RELEASE += /MAP
QMAKE_CFLAGS_RELEASE += /Zi
QMAKE_LFLAGS_RELEASE += /debug /opt:ref
}
2、实现崩溃异常的处理函数
#ifdef WIN32
#include <windows.h>
#include <dbghelp.h>
#include <QDir>
#pragma comment(lib,"dbghelp.lib")
#define COREFILE_DIR_PATH "C:\\corefile"
#define WCOREFILE_DIR_PATH L"C:\\corefile"
void CreateDumpFile(std::wstring lpstrDumpFilePathName, EXCEPTION_POINTERS *pException)
{
HANDLE hDumpFile = CreateFile(lpstrDumpFilePathName.c_str(), GENERIC_WRITE, 0, NULL, CREATE_ALWAYS, FILE_ATTRIBUTE_NORMAL, NULL);
MINIDUMP_EXCEPTION_INFORMATION dumpInfo;
dumpInfo.ExceptionPointers = pException;
dumpInfo.ThreadId = GetCurrentThreadId();
dumpInfo.ClientPointers = TRUE;
MiniDumpWriteDump(GetCurrentProcess(), GetCurrentProcessId(), hDumpFile, MiniDumpNormal, &dumpInfo, NULL, NULL);
CloseHandle(hDumpFile);
}
LONG WINAPI CrashHandler(EXCEPTION_POINTERS *pException)
{
std::wstring strDumpPath = WCOREFILE_DIR_PATH;
QDir dirSys(COREFILE_DIR_PATH);
if (!dirSys.exists())
{
dirSys.mkpath(COREFILE_DIR_PATH);
}
SYSTEMTIME time;
GetLocalTime(&time);
WCHAR szTime[128];
swprintf_s(szTime, L"%04d-%02d-%02d %02d-%02d-%02d-%03d", time.wYear, time.wMonth, time.wDay, time.wHour, time.wMinute, time.wSecond, time.wMilliseconds);
strDumpPath += L"\\";
strDumpPath += szTime;
strDumpPath += L"-xxxx.dmp";
CreateDumpFile(strDumpPath, pException);
return EXCEPTION_EXECUTE_HANDLER;
}
#endif
- 注册异常处理函数
#ifdef WIN32
SetUnhandledExceptionFilter((LPTOP_LEVEL_EXCEPTION_FILTER)CrashHandler);
#endif
经过上面几个步骤,qt在win下异常崩溃就可以捕获生成dump文件了。
- windbg分析dump文件
因为只是分析崩溃,windbg复杂的用法再次不做描述了,下面是分析堆栈的具体步骤:
- 装了vs的有自带的windbg,没有的话可以自行网上下一个。
- 选择symbol Search Path,将pdb文件路径加进去,以;为分隔符
- 选择源码路径,将所有包含代码的路径都加上
- 选择打开dunmp文件
- 在输入框中输入:.reload
- 再输入:!analyze –v
- 查看堆栈
三、linux下的崩溃
linux下程序崩溃,可以在系统中配置生成corefile文件,这个是系统自带的机制,配置下文件即可,不需代码实现,可以写个shell脚本,在脚本中调用下面函数
setCoreDumpFormat()
{
CORE_PATH=/corefile
if [ ! -d $CORE_PATH ]
then
mkdir $CORE_PATH
fi
echo "$CORE_PATH/core-%e-%p-%t" > /proc/sys/kernel/core_pattern
ulimit -c unlimited
}