Windows / C ++:是否有可能找到抛出异常的代码行,其中包含“Exception Offset”

时间:2010-03-27 09:42:23

标签: c++ windows exception

我们的一位用户在我们的产品启动时遇到异常。 她从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文件。

我希望我的问题不太天真。

4 个答案:

答案 0 :(得分:66)

是的,这是可能的。使用与用户运行的完全相同的二进制文件开始调试,确保已加载DLL并且您已获得匹配的PDB文件。在Debug + Windows + Modules中查找DLL基址。添加偏移量。 Debug + Windows + Disassembly并在Address字段中输入计算的地址(前缀为0x)。这会向您显示导致异常的确切机器代码指令。右键单击+转到源代码以查看匹配的源代码行。

虽然这显示了声明,但这通常不足以诊断原因。 0xc0000005异常是一种访问冲突,它有许多可能的原因。通常你甚至没有得到任何代码,由于堆栈损坏,程序可能已经被遗忘了。或者真正的问题位于很远的地方,一些指针操作破坏了堆。您通常还需要一个堆栈跟踪,向您展示程序如何在轰炸声明中结束。

你需要的是一个小型转储。如果她运行Vista或Win7,您可以轻松地从用户那里获得一个。启动TaskMgr.exe,进程选项卡,选择被轰炸的程序,同时它仍然显示崩溃对话框。右键单击它并创建转储文件。

为了使这个顺利,你真的想要自动化这个过程。你会在this thread中的答案中找到提示。

答案 1 :(得分:4)

如果你有一个minidump,在Visual Studio中打开它,将MODPATH设置为包含原始二进制文件和PDB的相应文件夹,并告诉它“运行”。您可能还需要告诉它从Microsoft符号服务器加载符号。它将在错误位置显示调用堆栈。如果您尝试查看特定堆栈位置的源代码,它可能会询问您的源位置;如果是这样,请选择适当的源文件夹。 MODPATH在具有minidump文件名称的“项目”的调试命令行属性中设置。

答案 2 :(得分:2)

我知道这个帖子已经很老了,但这是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

答案 3 :(得分:1)

与基于运行时的元数据感知语言(如.NET或Java)不同,源代码信息不会保留在已编译的C ++代码中。 PDB文件是一个符号索引,它可以帮助调试器将编译后的代码映射到源,但必须在程序执行期间完成,而不是从崩溃转储中完成。即使使用PDB,发布编译的代码也会受到许多优化,这些优化可能会阻止调试器识别源代码。

仅在最终用户计算机上显示的调试问题通常是仔细的状态记录和大量以细节为导向的时间和精力在源上进行梳理的问题。根据您与用户的关系(例如,如果您是内部企业IT开发),您可以创建用户计算机的虚拟机映像并将其用于调试,这可以通过精确地帮助加速该过程在用户工作站上复制已安装的软件和标准运行进程。