本文为学习记录,若有错误,请联系作者,谦虚受教。
文章目录
- 前言
- 一、目的
- 二、实现步骤
- 1 add2line.exe
- 2 分析文件
- 3 crash文件
- 三、相关代码
- 1 pro文件
- 2.ccrashstack.h
- 3.ccrashstack.cpp
- 4.main.cpp
- 总结
前言
你从来来去自由,若你不想要了跑开便是。
一、目的
发布的客户版本里分析崩溃原因,便于解决问题。
二、实现步骤
1 add2line.exe
在自己QT安装的目录下,例如:D:\Qt\Qt5.12.3\Tools\mingw730_32\bin,找到adde2line.exe。
将add2line.exe复制到自己发布的版本中。
2 分析文件
在代码里添加一个类和发布版本所在文件夹里添加addr2line.exe,后续程序崩溃后,会在工程文件中,代码生成一个MyApp文件夹,里面包含一个crash文件
3 crash文件
打开crash文件,找到自己addr。
打开QT的cmd,进入自己发布版本的路径。例如
1、cd D:\TEST\1QTTEST\Thermopile_HM\32X32\Client\V1.0.1Client\release
2、addr2line.exe -f -e 软件文件名 crash崩溃地址 (提示:中间要空格)
3、提示错误信息
三、相关代码
1 pro文件
在pro文件添加以下代码:
QMAKE_CFLAGS_RELEASE += -g
QMAKE_CXXFLAGS_RELEASE += -g
QMAKE_CFLAGS_RELEASE -= -O2
QMAKE_CXXFLAGS_RELEASE -= -O2
QMAKE_LFLAGS_RELEASE = -mthreads -W
2.ccrashstack.h
#ifndef CCRASHSTACK_H
#define CCRASHSTACK_H
#include <windows.h>
#include <QString>class ccrashstack
{
private:PEXCEPTION_POINTERS m_pException;
private:QString GetModuleByRetAddr(PBYTE Ret_Addr, PBYTE & Module_Addr);QString GetCallStack(PEXCEPTION_POINTERS pException);QString GetVersionStr();bool GetHardwareInaformation(QString &graphics_card, QString &sound_deivce);
public:ccrashstack(PEXCEPTION_POINTERS pException);QString GetExceptionInfo();
};#endif // CCRASHSTACK_H
3.ccrashstack.cpp
#include "ccrashstack.h"
#include <tlhelp32.h>
#include <stdio.h>#define _WIN32_DCOM
#include <comdef.h>
#include <Wbemidl.h>//#include<base/constants.h>
#include "qdebug.h"ccrashstack::ccrashstack(PEXCEPTION_POINTERS pException)
{m_pException = pException;
}QString ccrashstack::GetModuleByRetAddr(PBYTE Ret_Addr, PBYTE & Module_Addr)
{MODULEENTRY32 M = {sizeof(M)};HANDLE hSnapshot;wchar_t Module_Name[MAX_PATH] = {0};hSnapshot = CreateToolhelp32Snapshot(TH32CS_SNAPMODULE, 0);if ((hSnapshot != INVALID_HANDLE_VALUE) &&Module32First(hSnapshot, &M)){do{if (DWORD(Ret_Addr - M.modBaseAddr) < M.modBaseSize){lstrcpyn(Module_Name, M.szExePath, MAX_PATH);Module_Addr = M.modBaseAddr;break;}} while (Module32Next(hSnapshot, &M));}CloseHandle(hSnapshot);QString sRet = QString::fromWCharArray(Module_Name);return sRet;
}QString ccrashstack::GetCallStack(PEXCEPTION_POINTERS pException)
{PBYTE Module_Addr_1;char bufer[256]={0};QString sRet;typedef struct STACK{STACK * Ebp;PBYTE Ret_Addr;DWORD Param[0];} STACK, * PSTACK;STACK Stack = {0, 0};PSTACK Ebp;if (pException) //fake frame for exception address{Stack.Ebp = (PSTACK)pException->ContextRecord->Ebp;Stack.Ret_Addr = (PBYTE)pException->ExceptionRecord->ExceptionAddress;Ebp = &Stack;}else{Ebp = (PSTACK)&pException - 1; //frame addr of Get_Call_Stack()// Skip frame of Get_Call_Stack().if (!IsBadReadPtr(Ebp, sizeof(PSTACK)))Ebp = Ebp->Ebp; //caller ebp}// Break trace on wrong stack frame.for (; !IsBadReadPtr(Ebp, sizeof(PSTACK)) && !IsBadCodePtr(FARPROC(Ebp->Ret_Addr));Ebp = Ebp->Ebp){// If module with Ebp->Ret_Addr found.memset(bufer,0, sizeof(0));sprintf(bufer, "\n%08X ", (unsigned int)Ebp->Ret_Addr);sRet.append(bufer);QString moduleName = this->GetModuleByRetAddr(Ebp->Ret_Addr, Module_Addr_1) ;if (moduleName.length() > 0){sRet.append(moduleName);}}return sRet;
} //Get_Call_StackQString ccrashstack::GetVersionStr()
{OSVERSIONINFOEX V = {sizeof(OSVERSIONINFOEX)}; //EX for NT 5.0 and laterif (!GetVersionEx((POSVERSIONINFO)&V)){ZeroMemory(&V, sizeof(V));V.dwOSVersionInfoSize = sizeof(OSVERSIONINFO);GetVersionEx((POSVERSIONINFO)&V);}if (V.dwPlatformId != VER_PLATFORM_WIN32_NT)V.dwBuildNumber = LOWORD(V.dwBuildNumber); //for 9x HIWORD(dwBuildNumber) = 0x04xxQString sRet;sRet.append(QString("Windows: %1.%2.%3, SP %4.%5, Product Type %6\n").arg(V.dwMajorVersion).arg(V.dwMinorVersion).arg(V.dwBuildNumber).arg(V.wServicePackMajor).arg(V.wServicePackMinor).arg(V.wProductType));// QString graphics_module = "GraphicsCard: ";
// QString sound_module = "SoundDevice: ";
// GetHardwareInaformation(graphics_module, sound_module);
// sRet.append(graphics_module);
// sRet.append(sound_module);return sRet;
}QString ccrashstack::GetExceptionInfo()
{WCHAR Module_Name[MAX_PATH];PBYTE Module_Addr;QString sRet;char buffer[512]={0};QString sTmp = GetVersionStr();sRet.append(sTmp);sRet.append("Process: ");GetModuleFileName(NULL, Module_Name, MAX_PATH);sRet.append(QString::fromWCharArray(Module_Name));sRet.append("\n");// If exception occurred.if (m_pException){EXCEPTION_RECORD & E = *m_pException->ExceptionRecord;CONTEXT & C = *m_pException->ContextRecord;memset(buffer, 0, sizeof(buffer));sprintf(buffer, "Exception Addr: %08X ", (int)E.ExceptionAddress);sRet.append(buffer);// If module with E.ExceptionAddress found - save its path and date.QString module = GetModuleByRetAddr((PBYTE)E.ExceptionAddress, Module_Addr);if (module.length() > 0){sRet.append(" Module: ");sRet.append(module);}memset(buffer, 0, sizeof(buffer));sprintf(buffer, "\nException Code: %08X\n", (int)E.ExceptionCode);sRet.append(buffer);if (E.ExceptionCode == EXCEPTION_ACCESS_VIOLATION){// Access violation type - Write/Read.memset(buffer, 0, sizeof(buffer));sprintf(buffer,"%s Address: %08X\n",(E.ExceptionInformation[0]) ? "Write" : "Read", (int)E.ExceptionInformation[1]);sRet.append(buffer);}sRet.append("Instruction: ");for (int i = 0; i < 16; i++){memset(buffer, 0, sizeof(buffer));sprintf(buffer, " %02X", PBYTE(E.ExceptionAddress)[i]);sRet.append(buffer);}sRet.append("\nRegisters: ");memset(buffer, 0, sizeof(buffer));sprintf(buffer, "\nEAX: %08X EBX: %08X ECX: %08X EDX: %08X", (unsigned int)C.Eax,(unsigned int) C.Ebx, (unsigned int)C.Ecx, (unsigned int)C.Edx);sRet.append(buffer);memset(buffer, 0, sizeof(buffer));sprintf(buffer, "\nESI: %08X EDI: %08X ESP: %08X EBP: %08X", (unsigned int)C.Esi, (unsigned int)C.Edi, (unsigned int)C.Esp, (unsigned int)C.Ebp);sRet.append(buffer);memset(buffer, 0, sizeof(buffer));sprintf(buffer, "\nEIP: %08X EFlags: %08X", (unsigned int)C.Eip,(unsigned int) C.EFlags);sRet.append(buffer);} //if (pException)sRet.append("\nCall Stack:");QString sCallstack = this->GetCallStack(m_pException);sRet.append(sCallstack);return sRet;
}
4.main.cpp
int main(int argc, char *argv[])
{QApplication a(argc, argv);SetUnhandledExceptionFilter(callback);MainWindow w;w.show();return a.exec();
}
总结
善于总结,多进一步。