国产 无码 综合区,色欲AV无码国产永久播放,无码天堂亚洲国产AV,国产日韩欧美女同一区二区

QT--崩潰原因分析

這篇具有很好參考價(jià)值的文章主要介紹了QT--崩潰原因分析。希望對大家有所幫助。如果存在錯(cuò)誤或未考慮完全的地方,請大家不吝賜教,您也可以點(diǎn)擊"舉報(bào)違法"按鈕提交疑問。

本文為學(xué)習(xí)記錄,若有錯(cuò)誤,請聯(lián)系作者,謙虛受教。


前言

你從來來去自由,若你不想要了跑開便是。


一、目的

發(fā)布的客戶版本里分析崩潰原因,便于解決問題。

二、實(shí)現(xiàn)步驟

1 add2line.exe

在自己QT安裝的目錄下,例如:D:\Qt\Qt5.12.3\Tools\mingw730_32\bin,找到adde2line.exe。
QT--崩潰原因分析,qt,數(shù)據(jù)庫,開發(fā)語言
將add2line.exe復(fù)制到自己發(fā)布的版本中。
QT--崩潰原因分析,qt,數(shù)據(jù)庫,開發(fā)語言

2 分析文件

在代碼里添加一個(gè)類和發(fā)布版本所在文件夾里添加addr2line.exe,后續(xù)程序崩潰后,會(huì)在工程文件中,代碼生成一個(gè)MyApp文件夾,里面包含一個(gè)crash文件
QT--崩潰原因分析,qt,數(shù)據(jù)庫,開發(fā)語言
QT--崩潰原因分析,qt,數(shù)據(jù)庫,開發(fā)語言

3 crash文件

打開crash文件,找到自己addr。
QT--崩潰原因分析,qt,數(shù)據(jù)庫,開發(fā)語言
打開QT的cmd,進(jìn)入自己發(fā)布版本的路徑。例如
1、cd D:\TEST\1QTTEST\Thermopile_HM\32X32\Client\V1.0.1Client\release
2、addr2line.exe -f -e 軟件文件名 crash崩潰地址 (提示:中間要空格)
3、提示錯(cuò)誤信息
QT--崩潰原因分析,qt,數(shù)據(jù)庫,開發(fā)語言

三、相關(guān)代碼

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_Stack

QString ccrashstack::GetVersionStr()
{
        OSVERSIONINFOEX V = {sizeof(OSVERSIONINFOEX)};  //EX for NT 5.0 and later

        if (!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) = 0x04xx

        QString 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

long __stdcall   callback(_EXCEPTION_POINTERS*   excp)
{
    ccrashstack crashStack(excp);
    QString sCrashInfo = crashStack.GetExceptionInfo();

//    TCHAR my_documents[MAX_PATH];
//    SHGetFolderPath(NULL, CSIDL_DESKTOP, NULL, SHGFP_TYPE_CURRENT, my_documents);
//    QString file_path = QString::fromWCharArray(my_documents);
    QDir dir;
    QString file_path = dir.currentPath();

    QDir *folder_path = new QDir;
    bool exist = folder_path->exists(file_path.append("\\MyApp"));
    if(!exist)
    {
        folder_path->mkdir(file_path);
    }
    delete folder_path;
    folder_path = nullptr;

    QString sFileName = file_path + "\\crash.log";

    QFile file(sFileName);
    if (file.open(QIODevice::WriteOnly|QIODevice::Truncate))
    {
        file.write(sCrashInfo.toUtf8());
        file.close();
    }

    return   EXCEPTION_EXECUTE_HANDLER;
}

int main(int argc, char *argv[])
{
    QApplication a(argc, argv);
    SetUnhandledExceptionFilter(callback);
    MainWindow w;
    w.show();
    return a.exec();
}

總結(jié)

善于總結(jié),多進(jìn)一步。文章來源地址http://www.zghlxwxcb.cn/news/detail-645491.html

到了這里,關(guān)于QT--崩潰原因分析的文章就介紹完了。如果您還想了解更多內(nèi)容,請?jiān)谟疑辖撬阉鱐OY模板網(wǎng)以前的文章或繼續(xù)瀏覽下面的相關(guān)文章,希望大家以后多多支持TOY模板網(wǎng)!

本文來自互聯(lián)網(wǎng)用戶投稿,該文觀點(diǎn)僅代表作者本人,不代表本站立場。本站僅提供信息存儲(chǔ)空間服務(wù),不擁有所有權(quán),不承擔(dān)相關(guān)法律責(zé)任。如若轉(zhuǎn)載,請注明出處: 如若內(nèi)容造成侵權(quán)/違法違規(guī)/事實(shí)不符,請點(diǎn)擊違法舉報(bào)進(jìn)行投訴反饋,一經(jīng)查實(shí),立即刪除!

領(lǐng)支付寶紅包贊助服務(wù)器費(fèi)用

相關(guān)文章

  • QT基礎(chǔ)篇(13)QT5數(shù)據(jù)庫

    1.數(shù)據(jù)庫基本概念 數(shù)據(jù)庫(Database)是指存儲(chǔ)、管理和組織數(shù)據(jù)的集合。它是一個(gè)組織化的、可持久化的數(shù)據(jù)集合,用于支持?jǐn)?shù)據(jù)的存儲(chǔ)、檢索、更新和管理。 數(shù)據(jù)庫系統(tǒng)(Database System)是建立在計(jì)算機(jī)上的數(shù)據(jù)管理系統(tǒng),由數(shù)據(jù)庫、數(shù)據(jù)庫管理系統(tǒng)(DBMS)和應(yīng)用程序組成。

    2024年01月22日
    瀏覽(19)
  • Qt 無法連接MySQL數(shù)據(jù)庫

    Qt 5.15及之后版本缺少mysql驅(qū)動(dòng):qsqlmysql.dll、qsqlmysqld.dll 下載對應(yīng)版本驅(qū)動(dòng):https://github.com/thecodemonkey86/qt_mysql_driver/releases?page=2 拷貝至Qt安裝路徑下,例如 Qt5.15.25.15.2msvc2019_64pluginssqldrivers 根據(jù)mysql版本下載對應(yīng)mysql壓縮包https://downloads.mysql.com/archives/community/ 找到libmysql.dll、

    2024年04月12日
    瀏覽(28)
  • 九、Qt C++ 數(shù)據(jù)庫開發(fā)

    九、Qt C++ 數(shù)據(jù)庫開發(fā)

    《一、QT的前世今生》 《二、QT下載、安裝及問題解決(windows系統(tǒng))》 《三、Qt Creator使用》???? 《四、Qt 的第一個(gè)demo-CSDN博客》 《五、帶登錄窗體的demo》 《六、新建窗體時(shí),幾種窗體的區(qū)別》? 《七、Qt 信號(hào)和槽》? 《八、Qt C++ 畢業(yè)設(shè)計(jì)》 《九、Qt C++ 數(shù)據(jù)庫開發(fā)》 《

    2024年01月18日
    瀏覽(21)
  • QT mysql 驅(qū)動(dòng)-數(shù)據(jù)庫安裝以及qt連接ssl報(bào)錯(cuò)問題

    QT mysql 驅(qū)動(dòng)-數(shù)據(jù)庫安裝以及qt連接ssl報(bào)錯(cuò)問題

    文章末尾是引用筆記 配置MySQL8.0 環(huán)境變量 如果不配置MySQL環(huán)境變量,就不能在命令行直接輸入MySQL登錄命令。下面說如何配置MySQL的環(huán)境變量: 步驟1:在桌面上右擊【此電腦】圖標(biāo),在彈出的快捷菜單中選擇【屬性】菜單命令。 步驟2:打開【系統(tǒng)】窗口,單擊【高級系統(tǒng)設(shè)

    2024年01月20日
    瀏覽(27)
  • Qt 數(shù)據(jù)庫的注冊和登錄功能

    Qt 數(shù)據(jù)庫的注冊和登錄功能

    widget.h widget.cpp ?client.h client.cpp ?main函數(shù) 窗口設(shè)計(jì)部分 最終效果圖:

    2024年02月07日
    瀏覽(22)
  • QT+SQLite數(shù)據(jù)庫配置和使用

    QT+SQLite數(shù)據(jù)庫配置和使用

    一、簡介 1.1 SQLite(sql)是一款開源輕量級的數(shù)據(jù)庫軟件,不需要server,可以集成在其他軟件中,非常適合嵌入式系統(tǒng)。Qt5以上版本可以直接使用SQLite(Qt自帶驅(qū)動(dòng))。 二、下載和配置 2.1 SQLite下載官網(wǎng)下載鏈接 2.2 根據(jù)計(jì)算機(jī)的配置,選擇所需項(xiàng)目是64位還是32位下載對應(yīng)的壓

    2024年02月06日
    瀏覽(24)
  • Qt通過ODBC連接openGauss數(shù)據(jù)庫

    Qt通過ODBC連接openGauss數(shù)據(jù)庫

    本文就介紹了Qt通過ODBC連接opengauss數(shù)據(jù)庫的基礎(chǔ)內(nèi)容。 在.pro文件中添加一行引入 添加如下測試代碼 說明成功連接openGauss數(shù)據(jù)庫 什么是ODBC ODBC(Open Database Connectivity,開放數(shù)據(jù)庫互連)是由Microsoft公司基于X/OPEN CLI提出的用于訪問數(shù)據(jù)庫的應(yīng)用程序編程接口。應(yīng)用程序通過O

    2024年02月05日
    瀏覽(22)
  • 5、QT中SQLite數(shù)據(jù)庫的操作

    執(zhí)行數(shù)據(jù)庫操作的類: SQLite3的基礎(chǔ)教程 ①、創(chuàng)建數(shù)據(jù)庫的鏈接對象: ②、使用數(shù)據(jù)庫驅(qū)動(dòng) ③、設(shè)置數(shù)據(jù)庫的名稱(創(chuàng)建一個(gè)數(shù)據(jù)庫) ④、創(chuàng)建一張表 例子: 例子: ①、遍歷所有數(shù)據(jù)并保存 ②、對比數(shù)據(jù) 例子: 查詢數(shù)據(jù)的時(shí)候,必須要先把遍歷的數(shù)據(jù)保存在sqlQuery類中

    2024年02月09日
    瀏覽(19)
  • Ubuntu下QT操作Mysql數(shù)據(jù)庫

    Ubuntu下QT操作Mysql數(shù)據(jù)庫

    本篇總結(jié)一下一下Ubuntu下QT操作Mysql數(shù)據(jù)庫。 目錄 1. 啟動(dòng)Mysql數(shù)據(jù)庫服務(wù)器 2.查看QT支持的數(shù)據(jù)庫驅(qū)動(dòng) 3.連接數(shù)據(jù)庫 4. 增加表和記錄 5. 刪除記錄 6. 修改記錄 7. 查詢記錄 8.完整代碼和運(yùn)行效果 常見錯(cuò)誤總結(jié): (1) 數(shù)據(jù)庫服務(wù)沒啟動(dòng)報(bào)錯(cuò)信息 (2) 有QMYSQL驅(qū)動(dòng),連接數(shù)據(jù)缺失敗 /

    2024年02月09日
    瀏覽(20)
  • C++ Qt開發(fā):QSqlDatabase數(shù)據(jù)庫組件

    C++ Qt開發(fā):QSqlDatabase數(shù)據(jù)庫組件

    Qt 是一個(gè)跨平臺(tái)C++圖形界面開發(fā)庫,利用Qt可以快速開發(fā)跨平臺(tái)窗體應(yīng)用程序,在Qt中我們可以通過拖拽的方式將不同組件放到指定的位置,實(shí)現(xiàn)圖形化開發(fā)極大的方便了開發(fā)效率,本章將重點(diǎn)介紹 QSqlDatabase 數(shù)據(jù)庫模塊的常用方法及靈活運(yùn)用。 Qt SQL模塊是Qt框架的一部分,它

    2024年02月04日
    瀏覽(19)

覺得文章有用就打賞一下文章作者

支付寶掃一掃打賞

博客贊助

微信掃一掃打賞

請作者喝杯咖啡吧~博客贊助

支付寶掃一掃領(lǐng)取紅包,優(yōu)惠每天領(lǐng)

二維碼1

領(lǐng)取紅包

二維碼2

領(lǐng)紅包