1. 程式人生 > >Qt程式crash資訊的捕捉與跟蹤(qt-mingw)

Qt程式crash資訊的捕捉與跟蹤(qt-mingw)

在用qt編寫程式時經常會遇到崩潰問題,如果抓取不到crash堆疊資訊就會對崩潰問題束手無策,只能對其進行復現,推斷。

目錄

步驟1:

步驟2:

步驟3:

網友評論:

一般解決crash問題時有如下步驟:

  1. 從軟體發行版本能跟獲得debug資訊,在不同平臺下有不同的表現方式,目前只討論qt-mingw方式,這種方式可以利用修改工程檔案配置項編譯時講debug資訊加入應用程式當中;當然這會增加發行版應用程式的體積。如果想體積變小可以strip應用程式。
  2. 獲得crash堆疊資訊
  3. 根據crash堆疊資訊和1中的debug資訊來查詢軟體崩潰的位置。


如何執行以上3步驟,下面我詳細介紹如何操作;

步驟1:

在工程檔案.pro中加入如下程式碼,生成可執行檔案中就會帶debug資訊:
QMAKE_CXXFLAGS_RELEASE += -g

QMAKE_CFLAGS_RELEASE += -g

QMAKE_LFLAGS_RELEASE = -mthreads -Wl

前兩行意識意思為在release版本中增加debug資訊;第三行意思為release版本中去掉-s引數,這樣就生成對應符號表,可以除錯跟蹤;

步驟2:


(注:目前只討論windows平臺,linux和mac暫不討論;)

需要呼叫window平臺系統api進行擷取crash資訊及獲得crash堆疊。
首先在main函式中呼叫系統API SetUnhandledExceptionFilter

,該函式有個設定回撥函式,軟體崩潰時會回撥該系統函式,並傳回崩潰地址資訊等。

如何呼叫,請看如下程式碼:

long __stdcall   callback(_EXCEPTION_POINTERS*   excp)
{
    CCrashStack crashStack(excp);
    QString sCrashInfo = crashStack.GetExceptionInfo();
    QString sFileName = "testcrash.log";

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

    qDebug()<<"Error:\n"<<sCrashInfo;
    //MessageBox(0,L"Error",L"error",MB_OK);
    QMessageBox msgBox;
    msgBox.setText(QString::fromUtf8("親,我死了,重新啟動下吧!"));
    msgBox.exec();

    return   EXCEPTION_EXECUTE_HANDLER;
}

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

    QApplication a(argc, argv);
    Dialog w;
    w.show();

    return a.exec();
}

注:CCrashStack 是我寫的類,目的是呼叫系統API獲取crash堆疊資訊;(目前只針對windows平臺)

步驟3:

通過qt命令列進入 執行命令:
objdump -S xxx.exe >aaa.asm

命令執行完成後,根據步驟2中獲得的crash堆疊資訊在aaa.asm中查詢響應地址,即可得到崩潰具體位置。


附件為測試demo,裡面有完整程式碼,各位可下載體驗。

Demo下載地址:

http://download.csdn.net/detail/lanhy999/6341987

網友評論:

  • SHIXINGYA: EXE太大,asm生成不全,怎麼解決? asm生成到465350行就不寫了(8個月前#7樓)收起回覆

  • SHIXINGYA回覆 SHIXINGYA: http://www.qtcn.org/bbs/read-htm-tid-65581.html(8個月前)

  • 振星: 您好,我直接編譯您的程式碼,在release下編譯遇到該問題: g++: error: unrecognized command line option '-Wl' 我的環境是Qt 4.8.6,使用mingw編譯的。請問我是否還有什麼沒有地方沒有設定正確呢?(3年前#6樓)收起回覆

  • 嘆逍遙回覆 振星: http://stackoverflow.com/questions/22282871/unrecognized-command-line-option-wi http://stackoverflow.com/questions/21305309/g-doesnt-recognize-the-option-wl 我也碰到了,將那三行加入工程後release編譯報錯,根據第二篇討論的答案,我去掉-Wl之後編譯OK,後面又實驗了下-Wl後面加逗號也可以並且兩種編譯出的exe md5一樣,不知道實際編譯-Wl引數到底有沒有進去,不過感覺後面加逗號應該妥當一點 QMAKE_LFLAGS_RELEASE = -mthreads -Wl, 或者 QMAKE_LFLAGS_RELEASE = -mthreads(1年前)
  • fanweimianA: 命令執行完成後,根據步驟2中獲得的crash堆疊資訊在aaa.asm中查詢響應地址,即可得到崩潰具體位置 能否做個說明,是怎麼找到具體位置的,log檔案,asm檔案我都有了,不知道怎麼看,謝謝(4年前#5樓)收起回覆舉報回覆

  • 嘆逍遙回覆 嘆逍遙: 上面兩段分別是記錄的crash日誌和dump出的asm, Exception Addr: 00401E20 說明程式碼地址00401E20出發生異常,Write Address: 00000000說明異常的時候正在訪問0x00000000記憶體地址,對比asm中00401E20處,正好是博主構造的對空指標進行寫入的異常處。剩下的Registers和Call Stack儲存了現場的暫存器和堆疊資訊。 不過有個問題是這東西release版本帶著除錯資訊釋出,很容易被人看出原始碼,不過自己寫的小程式無所謂了 末尾感謝博主的分享!(1年前)
    • 嘆逍遙回覆 fanweimianA: 雖然時間挺久了,但是自己折騰了好長時間忍不住回覆一下: Exception Addr: 00401E20 Module: D:\QT\build-TestCrash-Desktop_Qt_5_8_0_MinGW_32bit-Release\release\TestCrash.exe Exception Code: C0000005 Write Address: 00000000 Instruction: C7 05 00 00 00 00 00 00 00 00 0F 0B 90 90 90 90 Registers: EAX: 00000000 EBX: 00000000 ECX: 0077FE04 EDX: 00000000 ESI: 0077D428 EDI: 0077FE04 ESP: 0077D31C EBP: 0077D408 EIP: 00401E20 EFlags: 00010246 Call Stack: 00401E20 D:\QT\build-TestCrash-Desktop_Qt_5_8_0_MinGW_32bit-Release\release\TestCrash.exe 620C2D1F C:\Qt\5.8\mingw53_32\bin\Qt5Widgets.dll void Dialog::on_btnTestCrash_clicked() { int *p = NULL; *p = 4; 401e20: c7 05 00 00 00 00 00 movl $0x0,0x0 401e27: 00 00 00 401e2a: 0f 0b ud2 401e2c: 90 nop 401e2d: 90 nop 401e2e: 90 nop 401e2f: 90 nop 00401e30 &lt;__ZL7sprintfPcPKcz&gt;: }(1年前)

  • sunlj181: 你好。這個資訊時怎麼對應的?(4年前#4樓)

  • aiolia0122: 命令執行完成後,根據步驟2中獲得的crash堆疊資訊在aaa.asm中查詢響應地址,即可得到崩潰具體位置 能否做個說明,是怎麼找到具體位置的,log檔案,asm檔案我都有了,不知道怎麼看,謝謝(4年前#3樓)

  • 資深碼農: 1.mingw 2.mingw下生成的符號和應用程式檔案是一起的;通過objdump命令可以產生出符號檔案;例如: objdump -s a.exe &gt;a.asm(4年前#2樓)

  • yanan_gd: 你好,問兩個問題 1.你給的這個demo的編譯環境是什麼,mingw還是msvs? 2.步驟1中的生成的符號檔案在哪裡? 謝謝(4年前#1樓)收起回覆

    • 資深碼農回覆 yanan_gd: 1.mingw 2.mingw下生成的符號和應用程式檔案是一起的;通過objdump命令可以產生出符號檔案;例如: objdump -s a.exe &gt;a.asm(4年前)

--------------------- 
作者:資深碼農 
來源:CSDN 
原文:https://blog.csdn.net/lanhy999/article/details/12189375 
版權宣告:本文為博主原創文章,轉載請附上博文連結!

相關推薦

Qt程式crash資訊捕捉跟蹤qt-mingw

在用qt編寫程式時經常會遇到崩潰問題,如果抓取不到crash堆疊資訊就會對崩潰問題束手無策,只能對其進行復現,推斷。 目錄 步驟1: 步驟2: 步驟3: 網友評論: 一般解決crash問題時有如下步驟: 從軟體發行版本能跟獲得debug資

Qt之Quazip的編譯使用壓縮檔案

1.QuaZip的的編譯依賴於zlib庫 Zlib庫下載地址: Zlib庫的下載地址 QuaZip的下載地址 QuaZipde 下載地址 編譯器: mingw32 Qt版本:Qt5.6.1; 本文下載的zlib庫的版本是:zlib-1.2.11 2.Zlib的編

C++ 異常捕捉處理try...catch...

首先舉一個異常處理的例子: string str = "0123456789"; char ch1 = str[100];    //陣列越界,但是不提醒,程式執行立即崩潰 cout << ch1 << endl;    &n

網路爬蟲_資訊標記提取學習筆記

慕課課程筆記 目錄 2.1 方法 2.2 例項 4. 小結 1. 資訊標記 1.1 資訊標記 標記後的資訊可形成資訊組織結構,增加了資訊維度 標記的結構與資訊一樣具有重要價值 標記後

程式開發之檔案作用域全域性變數模組化utils抽離工具類

檔案作用域 在 JavaScript 檔案中宣告的變數和函式只在該檔案中有效;不同的檔案中可以宣告相同名字的變數和函式,不會互相影響。 通過全域性函式 getApp() 可以獲取全域性的應用例項,如果需要全域性的資料可以在 App() 中設定, 例如: glob

記一個轉行程式設計師的工作經歷感想後期更新

前言 隨著科技的發展,現代人生活的節奏是越來越快,個人覺得程式設計師的生活節奏更快(個人觀點),在忙碌的生活中總是很難找到一點點的空閒時間(就算有,估計也是用來睡眠,不知道為什麼總是感覺程式設計師是一種睡眠不足的生物),但是一旦有時間就想通過文字記錄下來,作為以後生活的回憶

黑馬程式設計師——IO輸入輸出

--------------------- <a href="http://edu.csdn.net/heima" target="blank">android培訓</a>、<a href="http://edu.csdn.net/heima

visual studio 2010 內嵌 Qt 安裝配置無需編譯

Qt4.6和VS的整合,理論上Qt4.6以上版本都可以,這裡以4.8.4版本為例;自從Nokia出了Qt4.6.0之後,再想將Qt整合到VS2010中就方便多了,不需要使用者自己用VC編譯器去編譯Qt原始碼,因為官方已經發布了VS2010編譯好的庫,直接安裝就可以用了。安裝

字元編碼字符集Encoding&CharSet——害死多少程式設計師

           之前在書上看過編碼和字符集,也遇到一些亂碼問題。但是之前並沒有真正區分字符集和字元編碼。最後亂碼問題還是不能解決。一般在同一個語言、平臺上就能夠正確顯示,因為他們預設的字符集都是

lua錯誤資訊和回跟蹤Tracebacks

雖然你可以使用任何型別的值作為錯誤資訊,通常情況下,我們使用字串來描述遇到的錯誤。如果遇到內部錯誤(比如對一個非table的值使用索引下標訪問)Lua將自己產生錯誤資訊,否則Lua使用傳遞給error函式的引數作為錯誤資訊。不管在什麼情況下,Lua都儘可能清楚的描述問題發生

Linux程序啟動過程分析do_execve(可執行程式的載入和執行)---Linux程序的管理排程十一

execve系統呼叫 execve系統呼叫 我們前面提到了, fork, vfork等複製出來的程序是父程序的一個副本, 那麼如何我們想載入新的程式, 可以通過execve來載入和啟動新的程式。 x86架構下, 其實還實現了一個

【Java TCP/IP Socket】應用程式協議中訊息的成幀解析含程式碼

     程式間達成的某種包含了資訊交換的形式和意義的共識稱為協議,用來實現特定應用程式的協議叫做應用程式協議。大部分應用程式協議是根據由欄位序列組成的離散資訊定義的,其中每個欄位中都包含了一段以

Qt程式上線後,崩潰處理含微軟編譯器命令

C/C++ 編譯器選項用於 x64 的 Microsoft (R) C/C++ 優化編譯器 16.00.40219.01 版優化/O1 最小化空間 /O2 最大化速度 /Ob 內聯擴充套件(預設 n=0) /Od 禁用優化(預設) /Og 啟用全域性優化 /Oi[-] 啟用內部函式 /Os 優選程式碼空間 /

C# 在程式焦點之外捕捉按鍵操作鍵盤鉤子的使用

在程式中捕捉使用者的按鍵行為很容易,但是假如程式最小化了或者隱藏到系統托盤了,這時因為程式已經失去焦點了我們想捕捉按鍵行為就不是那麼容易了。怎麼辦呢?這就要使用鍵盤鉤子了。 關於鍵盤鉤子,下面這個網友描述的很詳盡,我就不班門弄斧了,轉載過來以備不時之需。原文:http://

Redis 的安裝使用單節點

方式 ase kcon $path 配置文件 alt png ces 一個 Redis 的安裝與使用(單節點) 環境:CentOS 6.5 Redis 版本:redis-3.0 (考慮到Redis3.0 在集群和性能提升方面的特性,rc 版為正式版的候選版

hadoop偽分布式集群搭建安裝ubuntu系統

log 結束 實的 變量 開啟 web 路徑 har ont 1:Vmware虛擬軟件裏面安裝好Ubuntu操作系統之後使用ifconfig命令查看一下ip; 2:使用Xsheel軟件遠程鏈接自己的虛擬機,方便操作。輸入自己ubuntu操作系統的賬號密碼之後就鏈接成

分布式架構實戰--ActiveMQ的安裝使用單節點

解壓 rain fin admins blank 生產者 new 安裝配置 節點 具體內容請參考樣例代碼和視頻教程: http://www.roncoo.com/course/view/85d6008fe77c4199b0cdd2885eaeee53 IP:192.16

Redis的安裝使用單節點

做了 imp redis3.0 修改 .gz 環境 red redis配置 $1 IP:192.168.4.111 環境:CentOS 6.6 Redis版本:redis-3.0 (考慮到Redis3.0在集群和性能提升方面的特性,rc版為正式版的候選版,而且很快就出正

自己主動升級系統的設計實現續2 -- 添加斷點續傳功能 附最新源代碼

blog down 決定 top lin dom itl com 關於 一.緣起      之前已經寫了兩篇關於自己主動升級系統OAUS的設計與實現的文章(第一篇、第二篇)。在為OAUS服務端添加自己主動檢測文件變更的功能(這樣每次部署版本號升級時,能夠節省非常多時間。

HDU 5967 小R手機動態樹

出現 else rotate bsp 所在 print target light tmp 【題目鏈接】 http://acm.hdu.edu.cn/showproblem.php?pid=5967 【題目大意】   給出一張圖,每個點僅連一條有向邊,或者不連