如何進行dump文件分析

當程序出現某些問題而無法重現時,我們需要通過分析dump文件來查找程序崩潰的原因。本文將從多個方面對分析dump文件做詳細的闡述。

一、轉儲文件內容

如何查看dump文件的內容?我們可以使用某些工具或者通過編寫代碼實現。

以下是使用C++讀取dump文件並輸出其內容的示例:

#include <Windows.h>
#include <Dbghelp.h>
#include <iostream>

const DWORD MaxDumpSize = 64 * 1024 * 1024;//最大處理文件大小,為64M。

void DumpFileContent(const char* dumpFilePath)
{
    HANDLE hFile = CreateFileA(dumpFilePath, GENERIC_READ, 0, NULL, OPEN_EXISTING, FILE_ATTRIBUTE_NORMAL, NULL);//以只讀的方式打開dump文件
    if (hFile == INVALID_HANDLE_VALUE)
    {
        std::cout << "Open dump file failed!" << std::endl;
        return;
    }
    HANDLE hMapping = CreateFileMapping(hFile, NULL, PAGE_READONLY, 0, 0, NULL);//創建文件映射
    if (hMapping == NULL)
    {
        CloseHandle(hFile);
        std::cout << "CreateFileMapping failed!" << std::endl;
        return;
    }
    LPVOID mapped = MapViewOfFile(hMapping, FILE_MAP_READ, 0, 0, 0);//內存映射文件
    if (mapped == NULL)
    {
        CloseHandle(hMapping);
        CloseHandle(hFile);
        std::cout << "MapViewOfFile failed!" << std::endl;
        return;
    }
    const DWORD dumpSize = GetFileSize(hFile, NULL);
    const DWORD viewSize = std::min(dumpSize, MaxDumpSize);
    std::cout << "file size: " << dumpSize << "; view size: " << viewSize << std::endl;
    for (DWORD i = 0; i < viewSize; i++)
    {
        const BYTE byte = *((BYTE*)mapped + i);
        std::cout << std::hex << static_cast<unsigned int>(byte) << " ";
    }
    std::cout << std::endl;
    UnmapViewOfFile(mapped);
    CloseHandle(hMapping);
    CloseHandle(hFile);
}

int main()
{
    DumpFileContent("test.dmp");
    return 0;
}

運行上述代碼後可以將輸出為dump文件的16進位格式。這樣的輸出對於一些低級錯誤或者複雜的bug是有用的。

二、查找錯誤位置

當程序崩潰時,我們需要查找錯誤的位置。我們可以使用VS的調試器來查找錯誤位置,也可以使用WinDbg等工具進行分析。

以下是使用WinDbg分析dump文件並查找錯誤位置的示例:

!analyze -v

使用上述命令可以分析dump文件並輸出詳細的錯誤信息。例如:

FAULTING_IP: 
+0
000007fe`fafffa55 ??              ???

EXCEPTION_RECORD:  ffffffffffffffff -- (.exr 0xffffffffffffffff)
ExceptionAddress: 000007fefafffa55
   ExceptionCode: c0000005 (Access violation)
  ExceptionFlags: 00000000
NumberParameters: 2
   Parameter[0]: 0000000000000000
   Parameter[1]: 00000000ffffffff
Attempt to read from address ffffffff

DEFAULT_BUCKET_ID:  INVALID_POINTER_READ

PROCESS_NAME:  test.exe

ERROR_CODE: (NTSTATUS) 0xc0000005 - 

EXCEPTION_CODE: (NTSTATUS) 0xc0000005 - 

EXCEPTION_PARAMETER1:  0000000000000000

EXCEPTION_PARAMETER2:  00000000ffffffff

READ_ADDRESS:  ffffffff 

FOLLOWUP_IP: 
test!main+1d [c:\test.cpp @ 12]
00000001`400115dd c3              ret

APP:  test.exe

FAULTING_THREAD:  00000000000005f8

BUGCHECK_STR:  APPLICATION_FAULT_INVALID_POINTER_READ

PRIMARY_PROBLEM_CLASS:  APPLICATION_FAULT

LAST_CONTROL_TRANSFER:  from 000007fefa3365f1 to 000007fefafffa55

STACK_TEXT:  
00000000`00eddc48 000007fe`fa3365f1 : 00000000`00e00c00 00000000`00000000 00000000`00000000 00000000`00000000 : 0x000007fe`fafffa55
00000000`00eddc50 00000001`400115dd : 00000000`00000000 00000000`00000000 00000000`00000000 00000000`00000000 : test!main+0x1d [c:\test.cpp @ 12]
00000000`00eddc80 00007ffc`c0d37d5d : 00000000`00eddeb8 00000000`77cf5961 00000000`00000000 00000000`00000000 : test!__tmainCRTStartup+0x159 [f:\dd\vctools\crt\crtw32\dllstuff\crtexe.c @ 618]
00000000`00eddcf0 00007ffc`c2663034 : 00000000`00000000 00000000`00000000 00000000`00000000 00000000`00000000 : KERNEL32!BaseThreadInitThunk+0xd
00000000`00eddd20 00000000`00000000 : 00000000`00000000 00000000`00000000 00000000`00000000 00000000`00000000 : ntdll!RtlUserThreadStart+0x21

上述結果提供了引起錯誤的地址和模塊、錯誤類型、錯誤線程等信息,可以較快地定位到錯誤位置。

三、查看線程堆棧

線程堆棧信息可以告訴我們程序在出現錯誤時的執行狀態,可以使用VS的調試器來查看線程堆棧信息,也可以使用WinDbg等工具進行分析。

以下是使用WinDbg查看線程堆棧信息的示例:

~#

使用上述命令可以輸出線程列表,例如:

.  0  Id: 29a4.3e68 Suspend: 0 Teb: 00000000`00e4a000 Unfrozen
 # Child-SP          RetAddr           Call Site
00 00000000`02acf8d8 000007fe`fa3365f1 user32!NtUserGetMessage+0x14
01 00000000`02acf8e0 00000001`400115dd test!main+0x1d [c:\test.cpp @ 12]
02 00000000`02acf910 00007ffc`c0d37d5d test!__tmainCRTStartup+0x159 [f:\dd\vctools\crt\crtw32\dllstuff\crtexe.c @ 618]
03 00000000`02acf980 00007ffc`c2663034 kernel32!BaseThreadInitThunk+0xd
04 00000000`02acfac0 00000000`00000000 ntdll!RtlUserThreadStart+0x21

上述結果提供了線程的堆棧信息,方便我們查看程序在出現錯誤時的執行狀態。

四、查看堆內存分配狀態

如果程序崩潰時存在內存泄漏等問題,我們需要查看堆內存分配狀態以便找到內存泄漏的根源。我們可以使用VS的調試器來查看內存泄漏情況,也可以使用WinDbg等工具進行分析。

以下是使用WinDbg查看堆內存分配狀態的示例:

!heap -s

使用上述命令可以輸出堆信息和分配情況統計,例如:

****************************************************************************************************************
                                                    HEAP SUMMARY:
****************************************************************************************************************
ProcessHeaps      20
   ---->  Heap      0000000000090000
         ****              0000000000010220 - 000000000002d91c ( 2902)     48000 bytes
         ...
         ****              00000000ffbaffa0 - 00000000ffba0000 (   144)       400 bytes
   ---->  Heap      00000000099b0000
         ****              00000000099b0240 - 0000000009a8a188 (  82261)   1688000 bytes
         ...
         ****              00000000099ec6f0 - 00000000099ec720 (      9)        36 bytes

    Large blocks (>=  512 KiB) detected:       1

    Total heap size:     9555940 bytes

    Total committed:     8491820 bytes

    Total free:            23436 bytes

    Max free block:        23436 bytes

    Largest reserve:     9192960 bytes

    Commited range:    0000000000090000 - 0000000009a83ff8
    Uncommited range:  0000000009a83ff8 - 0000000009c00000

    Virtual query: 001b0000 - 001c0000 00001000  MEM_PRIVATE MEM_COMMIT


****************************************************************************************************************
                                   Statistical Analysis of the Heap Manager Stats available at Global Heap Stat
****************************************************************************************************************

Heap         Count       Space(@)     Space($)          Map Space(@)  Map Space($)    Uncommitted($)   settable size($)   
------------------------------------------------------------------------------------------------------------------------

0000000000090000        9662      4861988      $    47490          2474836480             0         229376 

00000000099b0000          49         1536      $       23                0             0       9534976 

上述結果列出了堆的使用情況和統計數據,方便我們查看堆內存分配狀態。

五、查看函數調用樹

當程序出現錯誤時,我們可以使用函數調用樹查看程序執行的路徑。我們可以通過調用棧來查看函數調用樹,也可以使用VS的調試器或者WinDbg等工具進行分析。

以下是使用VS的調試器查看函數調用樹的示例:

在調試器的調用堆棧窗口中進行查看,該窗口用於顯示所有停止的線程的調用堆棧,可在調用堆棧窗口中選擇函數調用樹,以了解程序執行的路徑和順序。

六、結語

本文介紹了如何從多個方面分析dump文件,包括轉儲文件內容、查找錯誤位置、查看線程堆棧、查看堆內存分配狀態和查看函數調用樹等。

dump文件分析還有許多內容,需要我們不斷努力學習和實踐。希望本文對讀者有所幫助。

原創文章,作者:小藍,如若轉載,請註明出處:https://www.506064.com/zh-tw/n/254299.html

(0)
打賞 微信掃一掃 微信掃一掃 支付寶掃一掃 支付寶掃一掃
小藍的頭像小藍
上一篇 2024-12-14 17:41
下一篇 2024-12-14 17:41

相關推薦

  • vue下載無後綴名的文件被加上後綴.txt,有後綴名的文件下載正常問題的解決

    本文旨在解決vue下載無後綴名的文件被加上後綴.txt,有後綴名的文件下載正常的問題,提供完整的代碼示例供參考。 一、分析問題 首先,需了解vue中下載文件的情況。一般情況下,我們…

    編程 2025-04-29
  • 如何在Java中拼接OBJ格式的文件並生成完整的圖像

    OBJ格式是一種用於表示3D對象的標準格式,通常由一組頂點、面和紋理映射坐標組成。在本文中,我們將討論如何將多個OBJ文件拼接在一起,生成一個完整的3D模型。 一、讀取OBJ文件 …

    編程 2025-04-29
  • Python程序文件的拓展

    Python是一門功能豐富、易於學習、可讀性高的編程語言。Python程序文件通常以.py為文件拓展名,被廣泛應用於各種領域,包括Web開發、機器學習、科學計算等。為了更好地發揮P…

    編程 2025-04-29
  • 為什麼用cmd運行Java時需要在文件內打開cmd為中心

    在Java開發中,我們經常會使用cmd在命令行窗口運行程序。然而,有時候我們會發現,在運行Java程序時,需要在文件內打開cmd為中心,這讓很多開發者感到疑惑,那麼,為什麼會出現這…

    編程 2025-04-29
  • Python中讀入csv文件數據的方法用法介紹

    csv是一種常見的數據格式,通常用於存儲小型數據集。Python作為一種廣泛流行的編程語言,內置了許多操作csv文件的庫。本文將從多個方面詳細介紹Python讀入csv文件的方法。…

    編程 2025-04-29
  • Python zipfile解壓文件亂碼處理

    本文主要介紹如何在Python中使用zipfile進行文件解壓的處理,同時詳細討論在解壓文件時可能出現的亂碼問題的各種解決辦法。 一、zipfile解壓文件亂碼問題的根本原因 在P…

    編程 2025-04-29
  • Python將矩陣存為CSV文件

    CSV文件是一種通用的文件格式,在統計學和計算機科學中非常常見,一些數據分析工具如Microsoft Excel,Google Sheets等都支持讀取CSV文件。Python內置…

    編程 2025-04-29
  • Python如何導入py文件

    Python是一種開源的高級編程語言,因其易學易用和強大的生態系統而備受青睞。Python的import語句可以幫助用戶將一個模塊中的代碼導入到另一個模塊中,從而實現代碼的重用。本…

    編程 2025-04-29
  • Python合併多個相同表頭文件

    對於需要合併多個相同表頭文件的情況,我們可以使用Python來實現快速的合併。 一、讀取CSV文件 使用Python中的csv庫讀取CSV文件。 import csv with o…

    編程 2025-04-29
  • Python寫文件a

    Python語言是一種功能強大、易於學習、通用並且高級編程語言,它具有許多優點,其中之一就是能夠輕鬆地進行文件操作。文件操作在各種編程中都佔有重要的位置,Python作為開發人員常…

    編程 2025-04-29

發表回復

登錄後才能評論