簡體   English   中英

Windows/C++:是否可以找到拋出異常的代碼行,並具有“異常偏移”

[英]Windows/C++: Is it possible to find the line of code where exception was thrown having "Exception Offset"

我們的一位用戶在我們的產品啟動時遇到了異常。 她從 Windows 向我們發送了以下錯誤消息:

  Problem Event Name:                        APPCRASH
  Application Name:                          program.exe
  Application Version:                       1.0.0.1
  Application Timestamp:                     4ba62004
  Fault Module Name:                         agcutils.dll
  Fault Module Version:                      1.0.0.1
  Fault Module Timestamp:                    48dbd973
  Exception Code:                            c0000005
  Exception Offset:                          000038d7
  OS Version:                                6.0.6002.2.2.0.768.2
  Locale ID:                                 1033
  Additional Information 1:                  381d
  Additional Information 2:                  fdf78cd6110fd6ff90e9fff3d6ab377d
  Additional Information 3:                  b2df
  Additional Information 4:                  a3da65b92a4f9b2faa205d199b0aa9ef

是否可以通過此信息在源代碼中找到發生異常的確切位置?

Windows 上的 C++ 程序員用於定位用戶計算機上發生錯誤的位置的常用技術是什么?

我們的項目使用Release配置編譯,生成PDB文件。

我希望我的問題不是太天真。

是的,這是可能的。 使用與用戶運行的完全相同的二進制文件開始調試,確保已加載DLL並且您已獲得匹配的PDB文件。 在Debug + Windows + Modules中查找DLL基址。 添加偏移量。 Debug + Windows + Disassembly並在Address字段中輸入計算的地址(前綴為0x)。 這會向您顯示導致異常的確切機器代碼指令。 右鍵單擊+轉到源代碼以查看匹配的源代碼行。

雖然這顯示了聲明,但這通常不足以診斷原因。 0xc0000005異常是一種訪問沖突,它有許多可能的原因。 通常你甚至沒有得到任何代碼,由於堆棧損壞,程序可能已經被遺忘了。 或者真正的問題位於很遠的地方,一些指針操作破壞了堆。 您通常還需要一個堆棧跟蹤,向您展示程序如何在轟炸聲明中結束。

你需要的是一個小型轉儲。 如果她運行Vista或Win7,您可以輕松地從用戶那里獲得一個。 啟動TaskMgr.exe,進程選項卡,選擇被轟炸的程序,同時它仍然顯示崩潰對話框。 右鍵單擊它並創建轉儲文件。

為了使這個順利,你真的想要自動化這個過程。 您將在此主題中找到我的答案中的提示。

如果你有一個minidump,在Visual Studio中打開它,將MODPATH設置為包含原始二進制文件和PDB的相應文件夾,並告訴它“運行”。 您可能還需要告訴它從Microsoft符號服務器加載符號。 它將在錯誤位置顯示調用堆棧。 如果您嘗試查看特定堆棧位置的源代碼,它可能會詢問您的源位置; 如果是這樣,請選擇適當的源文件夾。 MODPATH在具有minidump文件名稱的“項目”的調試命令行屬性中設置。

我知道這個帖子已經很老了,但這是Google的一個重要回復,所以我想添加我的$ .02。

雖然迷你轉儲最有用,但只要您編譯了啟用符號的代碼(只發送沒有.pdb的文件,並保留.pdb!),您可以查找使用MSVC調試器或Windows調試器。 MSN上的文章:

http://blogs.msdn.com/b/danielvl/archive/2010/03/03/getting-the-line-number-for-a-faulting-application-error.aspx

與基於運行時的元數據感知語言(如.NET或Java)不同,源代碼信息不會保留在已編譯的C ++代碼中。 PDB文件是一個符號索引,它可以幫助調試器將編譯后的代碼映射到源,但必須在程序執行期間完成,而不是從崩潰轉儲中完成。 即使使用PDB,發布編譯的代碼也會受到許多優化,這些優化可能會阻止調試器識別源代碼。

僅在最終用戶機器上顯示的調試問題通常是仔細的狀態記錄和大量以細節為導向的時間和精力在源上進行梳理的問題。 根據您與用戶的關系(例如,如果您是內部企業IT開發),您可以創建用戶計算機的虛擬機映像並將其用於調試,這可以通過精確地幫助加速該過程在用戶工作站上復制已安裝的軟件和標准運行進程。

有幾種方法可以在事后找到崩潰位置。

  1. 使用小型轉儲。 請參閱上面的答案。
  2. 在調試器中使用現有的可執行文件。 請參閱上面的答案。
  3. 如果您有 PDB 文件(Visual Studio、Visual Basic 6),請使用DbgHelpBrowser加載 PDB 文件並查詢崩潰位置。
  4. 如果您有 TDS 文件(單獨的 TDS 文件,或嵌入 exe、Delphi、C++ Builder 32 位),請使用TDS 瀏覽器加載 TDS/DLL/EXE 文件並查詢崩潰位置。
  5. 如果您有 DWARF 符號(嵌入在 EXE、C++ Builder 64 位、gcc、g++ 中),請使用DWARF 瀏覽器加載 DLL/EXE 並查詢崩潰位置。
  6. 如果您有 MAP 文件,請使用MAP 文件瀏覽器加載 MAP 文件並查詢崩潰位置。

我編寫了這些工具供內部使用。 我們免費提供了它們。

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM