繁体   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