天天看點

Qt-生成dump檔案簡介Qt + MSVC編譯器

簡介

  之前轉載過一片文章Qt–讓你的用戶端崩潰之前生成dump檔案,文章中介紹了如何生成crash日志,不夠形象直覺,如果能夠生成用vs打開的dump檔案那就更好了,下面開始介紹。

Qt + MSVC編譯器

   這種情況其實比較簡單,我們直接在qmale建構配置的地方的額外的參數項上加上"CONFIG+=force_debug_info" "CONFIG+=separate_debug_info"即可,主要用來生成pdb檔案。

Qt-生成dump檔案簡介Qt + MSVC編譯器

Dump轉儲函數Helper.h頭檔案:

#pragma once
#include <tchar.h>
#include <Windows.h>
#include <DbgHelp.h>

#pragma comment(lib, "user32.lib")

int GenerateMiniDump(PEXCEPTION_POINTERS pExceptionPointers)
{
	// 定義函數指針
	typedef BOOL(WINAPI * MiniDumpWriteDumpT)(
		HANDLE,
		DWORD,
		HANDLE,
		MINIDUMP_TYPE,
		PMINIDUMP_EXCEPTION_INFORMATION,
		PMINIDUMP_USER_STREAM_INFORMATION,
		PMINIDUMP_CALLBACK_INFORMATION
		);
	// 從 "DbgHelp.dll" 庫中擷取 "MiniDumpWriteDump" 函數
	MiniDumpWriteDumpT pfnMiniDumpWriteDump = NULL;
	HMODULE hDbgHelp = LoadLibrary(_T("DbgHelp.dll"));
	if (NULL == hDbgHelp)
	{
		return EXCEPTION_CONTINUE_EXECUTION;
	}
	pfnMiniDumpWriteDump = (MiniDumpWriteDumpT)GetProcAddress(hDbgHelp, "MiniDumpWriteDump");

	if (NULL == pfnMiniDumpWriteDump)
	{
		FreeLibrary(hDbgHelp);
		return EXCEPTION_CONTINUE_EXECUTION;
	}
	// 建立 dmp 檔案件
	TCHAR szFileName[MAX_PATH] = { 0 };
    TCHAR szVersion[] = L"DumpFile";
	SYSTEMTIME stLocalTime;
	GetLocalTime(&stLocalTime);
	wsprintf(szFileName, L"%s-%04d%02d%02d-%02d%02d%02d.dmp",
		szVersion, stLocalTime.wYear, stLocalTime.wMonth, stLocalTime.wDay,
		stLocalTime.wHour, stLocalTime.wMinute, stLocalTime.wSecond);
	HANDLE hDumpFile = CreateFile(szFileName, GENERIC_READ | GENERIC_WRITE,
		FILE_SHARE_WRITE | FILE_SHARE_READ, 0, CREATE_ALWAYS, 0, 0);
	if (INVALID_HANDLE_VALUE == hDumpFile)
	{
		FreeLibrary(hDbgHelp);
		return EXCEPTION_CONTINUE_EXECUTION;
	}
	// 寫入 dmp 檔案
	MINIDUMP_EXCEPTION_INFORMATION expParam;
	expParam.ThreadId = GetCurrentThreadId();
	expParam.ExceptionPointers = pExceptionPointers;
	expParam.ClientPointers = FALSE;
	pfnMiniDumpWriteDump(GetCurrentProcess(), GetCurrentProcessId(),
		hDumpFile, MiniDumpWithDataSegs, (pExceptionPointers ? &expParam : NULL), NULL, NULL);
	// 釋放檔案
	CloseHandle(hDumpFile);
	FreeLibrary(hDbgHelp);
	return EXCEPTION_EXECUTE_HANDLER;
}

LONG WINAPI ExceptionFilter(LPEXCEPTION_POINTERS lpExceptionInfo)
{
	// 這裡做一些異常的過濾或提示
    if (IsDebuggerPresent()) {
		return EXCEPTION_CONTINUE_SEARCH;
	}
	return GenerateMiniDump(lpExceptionInfo);
}

           

調用:

#include <QApplication>
#include "Helper.h"

int main(int argc, char *argv[])
{
    SetUnhandledExceptionFilter(ExceptionFilter);

    QApplication a(argc, argv);

    int *p = nullptr;
    *p = 100;

    return a.exec();
}
           

  給一個空指針指派程式肯定會crash掉。

  然後我們将pdb檔案和生成dump檔案拷貝到源碼目錄:

Qt-生成dump檔案簡介Qt + MSVC編譯器
Qt-生成dump檔案簡介Qt + MSVC編譯器
Qt-生成dump檔案簡介Qt + MSVC編譯器

然後用VS2015打開dump檔案:

Qt-生成dump檔案簡介Qt + MSVC編譯器

點選設定符号路徑,選擇Microsoft符号伺服器,點選确認,第一次的話時間會比較長,耐心等待:

Qt-生成dump檔案簡介Qt + MSVC編譯器

然後點選使用僅限本機調試,然後會定位到出問題的代碼的位置,會出現調試資訊,非常友善:

Qt-生成dump檔案簡介Qt + MSVC編譯器
Qt-生成dump檔案簡介Qt + MSVC編譯器

使用google的breakpad架構

關于breakpad的架構在Qt中的使用,這篇文章講的很好,大家可以參看下。

https://github.com/JPNaude/dev_notes/wiki/Using-Google-Breakpad-with-Qt

繼續閱讀