Share via


損毀傾印分析

並非所有 Bug 都可以在發行前找到,這表示並非所有擲回例外狀況的 Bug 都可以在發行前找到。 幸運的是,Microsoft 已包含在 Platform SDK 中,此函式可協助開發人員收集使用者探索到之例外狀況的資訊。 MiniDumpWriteDump 函式會將必要的損毀傾印資訊寫入檔案,而不會儲存整個進程空間。 這個損毀傾印資訊檔案稱為小型傾印。 本技術文章提供如何撰寫和使用小型傾印的相關信息。

撰寫迷你傾印

撰寫迷你傾印的基本選項如下:

  • 不執行任何動作。 每當程序擲回未處理的例外狀況時,Windows 就會自動產生小型傾印。 自 Windows XP 以來,可以使用自動產生小型傾印。 如果使用者允許,小型傾印將會透過 Windows 錯誤報告 (WER) 傳送給 Microsoft,而不是傳送給開發人員。 開發人員可以透過 Windows 傳統型應用程式程式取得這些迷你傾印的存取權。

    使用 WER 需要:

    • 開發人員使用 Authenticode 簽署其應用程式
    • 應用程式在每個可執行檔和 DLL 中都有有效的 VERSIONINFO 資源

    如果您針對未處理的例外狀況實作自定義例程,則強烈建議您在例外狀況處理程式中使用 ReportFault 函式,以將自動化小型傾印傳送至 WER。 ReportFault式會處理連線至 WER 和傳送迷你傾印的所有問題。 未將迷你傾印傳送至 WER 違反了 Windows 遊戲的需求。

    如需 WER 的詳細資訊,請參閱 Windows 錯誤報告

  • 使用來自 Microsoft Visual Studio Team System 的產品。 在 [偵錯] 功能表上,單擊 [另存新檔] 以儲存傾印複本。 使用本機儲存的傾印只是內部測試和偵錯的選項。

  • 將程式代碼新增至您的專案。 新增 MiniDumpWriteDump 函式和適當的例外狀況處理程式碼,以儲存並直接傳送小型傾印給開發人員。 本文示範如何實作此選項。 不過,請注意 ,MiniDumpWriteDump 目前不適用於 Managed 程式代碼,而且僅適用於 Windows XP、Windows Vista、Windows 7。

執行緒安全

MiniDumpWriteDump 是 DBGHELP 連結庫的一部分。 此連結庫不是安全線程,因此任何使用 MiniDumpWriteDump 的程式都應該先同步處理所有線程,然後再嘗試呼叫 MiniDumpWriteDump

使用程式代碼撰寫迷你傾印

實際的實作很簡單。 以下是如何使用 MiniDumpWriteDump 的簡單範例。

#include <dbghelp.h>
#include <shellapi.h>
#include <shlobj.h>

int GenerateDump(EXCEPTION_POINTERS* pExceptionPointers)
{
    BOOL bMiniDumpSuccessful;
    WCHAR szPath[MAX_PATH]; 
    WCHAR szFileName[MAX_PATH]; 
    WCHAR* szAppName = L"AppName";
    WCHAR* szVersion = L"v1.0";
    DWORD dwBufferSize = MAX_PATH;
    HANDLE hDumpFile;
    SYSTEMTIME stLocalTime;
    MINIDUMP_EXCEPTION_INFORMATION ExpParam;

    GetLocalTime( &stLocalTime );
    GetTempPath( dwBufferSize, szPath );

    StringCchPrintf( szFileName, MAX_PATH, L"%s%s", szPath, szAppName );
    CreateDirectory( szFileName, NULL );

    StringCchPrintf( szFileName, MAX_PATH, L"%s%s\\%s-%04d%02d%02d-%02d%02d%02d-%ld-%ld.dmp", 
               szPath, szAppName, szVersion, 
               stLocalTime.wYear, stLocalTime.wMonth, stLocalTime.wDay, 
               stLocalTime.wHour, stLocalTime.wMinute, stLocalTime.wSecond, 
               GetCurrentProcessId(), GetCurrentThreadId());
    hDumpFile = CreateFile(szFileName, GENERIC_READ|GENERIC_WRITE, 
                FILE_SHARE_WRITE|FILE_SHARE_READ, 0, CREATE_ALWAYS, 0, 0);

    ExpParam.ThreadId = GetCurrentThreadId();
    ExpParam.ExceptionPointers = pExceptionPointers;
    ExpParam.ClientPointers = TRUE;

    bMiniDumpSuccessful = MiniDumpWriteDump(GetCurrentProcess(), GetCurrentProcessId(), 
                    hDumpFile, MiniDumpWithDataSegs, &ExpParam, NULL, NULL);

    return EXCEPTION_EXECUTE_HANDLER;
}


void SomeFunction()
{
    __try
    {
        int *pBadPtr = NULL;
        *pBadPtr = 0;
    }
    __except(GenerateDump(GetExceptionInformation()))
    {
    }
}

此範例示範 MiniDumpWriteDump 的基本用法,以及呼叫它所需的最小資訊。 傾印檔案的名稱由開發人員決定;不過,若要避免檔名衝突,建議您從應用程式的名稱和版本號碼、進程和線程標識碼,以及日期和時間產生檔名。 這也有助於讓小型傾印依應用程式和版本分組。 開發人員決定使用多少資訊來區分小型傾印檔名。

請注意,上述範例中的路徑名稱是由呼叫 GetTempPath 函式所產生,以擷取針對暫存盤指定之目錄的路徑。 即使使用最低許可權的用戶帳戶,使用此目錄也可防止小型傾印在不再需要硬碟空間后佔用硬碟空間。

如果您在每日建置程式期間封存產品,也請務必包含組建的符號,以便在必要時偵錯舊版的產品。 您也需要採取步驟,以在產生符號時維護完整的編譯程序優化。 這可以藉由在開發環境中開啟項目的屬性,並針對發行組態執行下列動作來完成:

  1. 在專案屬性頁的左側,按兩下 [C/C++]。 根據預設,這會顯示 [ 一般 ] 設定。 在項目屬性頁的右側,將 [偵錯資訊格式] 設定Program Database (/Zi)
  2. 在屬性頁的左側,展開 [鏈接器],然後按兩下 [ 偵錯]。 在屬性頁右側,將 [產生偵錯資訊 ] 設定 [是] (/DEBUG)。
  3. 按一下 [ 優化 ],並將 [參考 ] 設定 為 Eliminate 未推斷的資料 (/OPT:REF)
  4. 將 [啟用 COMDAT 折迭 ] 設定 移除多餘的 COMDAT (/OPT:ICF)。

MSDN 有MINIDUMP_EXCEPTION_INFORMATION 結構和 MiniDumpWriteDump 函式的詳細資訊。

使用 Dumpchk.exe

Dumpchk.exe 是命令列公用程式,可用來驗證傾印檔案是否已正確建立。 如果 Dumpchk.exe 產生錯誤,則傾印檔案已損毀且無法分析。 如需使用 Dumpchk.exe 的詳細資訊,請參閱 如何使用 Dumpchk.exe 檢查記憶體傾印檔案

Dumpchk.exe 包含在 Windows XP 產品 CD 上,而且可以在 Windows XP 產品 CD 的 Support\Tools\ 資料夾中執行 Setup.exe,安裝到系統磁片磁碟機\Program Files\Support Tools\ 。 您也可以下載並安裝 Windows 硬體開發人員中心 Windows 偵錯工具所提供的偵錯工具 ,以取得最新版本的 Dumpchk.exe。

分析迷你傾印

開啟小型傾印進行分析,就像建立一個縮排一樣簡單。

分析小型傾印

  1. 開啟 Visual Studio。
  2. 在 [ 檔案] 功能表上,按一下 [ 開啟專案 ]。
  3. 將 [檔案類型] 設定 為 [ 傾印檔案 ]、流覽至傾印檔案、選取它,然後按一下 [ 開啟]。
  4. 執行偵錯工具。

偵錯工具會建立模擬進程。 模擬進程將會在造成當機的指令中停止。

使用 Microsoft 公用符號伺服器

若要取得驅動程式或系統層級損毀的堆疊,可能需要將 Visual Studio 設定為指向 Microsoft 公用符號伺服器。

設定 Microsoft 符號伺服器的路徑

  1. 在 [ 偵錯] 功能表上,按一下 [ 選項 ]。
  2. 在 [ 選項 ] 對話方塊中,開啟 [ 偵錯] 節點,然後按一下 [ 符號 ]。
  3. 除非您要在偵錯時手動載入 符號,否則請確定 只有在未選取符號時,才搜尋上述位置。
  4. 如果您在遠端符號伺服器上使用符號,您可以藉由指定可複製符號的本機目錄來改善效能。 若要這樣做,請輸入從符號伺服器到此目錄 快取符號路徑。 若要連線到 Microsoft 公用符號伺服器,您必須啟用此設定。 請注意,如果您要對遠端電腦上的程式進行偵錯,快取目錄會參考遠端電腦上的目錄。
  5. 按一下 [確定]
  6. 因為您使用的是 Microsoft 公用符號伺服器,因此會出現 [使用者授權合約] 對話方塊。 按一下 [ ] 以接受合約,並將符號下載至本機快取。

使用 WinDbg 對 Minidump 進行偵錯

您也可以使用屬於 Windows 偵錯工具一部分的偵錯工具 WinDbg 來偵錯小型傾印。 WinDbg 可讓您偵錯,而不需要使用 Visual Studio。 若要下載 Windows 偵錯工具,請參閱 Windows 硬體開發人員中心 上的 Windows 偵錯工具 。

安裝 Windows 偵錯工具之後,您必須在 WinDbg 中輸入符號路徑。

在 WinDbg 中輸入符號路徑

  1. 在 [ 檔案] 功能表上,按一下 [ 符號路徑 ]。

  2. 在 [ 符號搜尋路徑 ] 視窗中,輸入下列專案:

    "srv\*c:\\cache\*https://msdl.microsoft.com/download/symbols;"

搭配使用 Copy-Protection Tools 搭配 Minidumps

開發人員也需要瞭解其禁止複製配置如何影響小型傾印。 大部分的禁止複製配置都有自己的解構工具,而且開發人員必須瞭解如何搭配 MiniDumpWriteDump 使用這些工具。

摘要

MiniDumpWriteDump 函式在產品發行後,在收集和解決 Bug 方面可能非常有用。 撰寫使用 MiniDumpWriteDump 的自訂例外狀況處理常式,可讓開發人員自訂資訊集合並改善偵錯程式。 函式具有足夠的彈性,可用於任何以 C++ 為基礎的專案,而且應該視為任何專案的穩定性程式的一部分。