Windows/C++:是否有可能找到抛出异常的代码行具有“异常偏移”
声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow
原文地址: http://stackoverflow.com/questions/2528776/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me):
StackOverFlow
Windows/C++: Is it possible to find the line of code where exception was thrown having "Exception Offset"
提问by Pavel
One of our users having an Exception on our product startup. She has sent us the following error message from Windows:
我们的一位用户在我们的产品启动时遇到了异常。她从 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
Is it possible to locate the exact place in the source code where the exception has occured having this information?
是否可以通过此信息在源代码中找到发生异常的确切位置?
What is the common technique for C++ programmers on Windows to locate the place of an error that has occured on user computer?
Windows 上的 C++ 程序员用于定位用户计算机上发生错误的位置的常用技术是什么?
Our project is compiled with Release configuration, PDB file is generated.
我们的项目使用Release配置编译,生成PDB文件。
I hope my question is not too naive.
我希望我的问题不是太天真。
回答by Hans Passant
Yes, that's possible. Start debugging with the exact same binaries as ran by your user, make sure the DLL is loaded and you've got a matching PDB file for it. Look in Debug + Windows + Modules for the DLL base address. Add the offset. Debug + Windows + Disassembly and enter the calculated address in the Address field (prefix with 0x). That shows you the exact machine code instruction that caused the exception. Right-click + Go To Source code to see the matching source code line.
是的,这是可能的。使用与您的用户运行的完全相同的二进制文件开始调试,确保 DLL 已加载,并且您有一个匹配的 PDB 文件。在 Debug + Windows + Modules 中查找 DLL 基地址。添加偏移量。调试 + Windows + 反汇编并在地址字段中输入计算出的地址(前缀为 0x)。这向您显示了导致异常的确切机器代码指令。右键单击 + Go To Source code 以查看匹配的源代码行。
While that shows you the statement, this isn't typically good enough to diagnose the cause. The 0xc0000005 exception is an access violation, it has many possible causes. Often you don't even get any code, the program may have jumped into oblivion due to a corrupted stack. Or the real problem is located far away, some pointer manipulation that corrupted the heap. You also typically really need a stack trace that shows you how the program ended up at the statement that bombed.
虽然这向您展示了该声明,但这通常不足以诊断原因。0xc0000005 异常是访问冲突,它有很多可能的原因。通常你甚至没有得到任何代码,程序可能由于堆栈损坏而被遗忘。或者真正的问题位于很远的地方,一些破坏堆的指针操作。您通常还需要一个堆栈跟踪来显示程序如何在被轰炸的语句处结束。
What you need is a minidump. You can easily get one from your user if she runs Vista or Win7. Start TaskMgr.exe, Processes tab, select the bombed program while it is still displaying the crash dialog. Right-click it and Create Dump File.
你需要的是一个小型转储。如果她运行 Vista 或 Win7,您可以轻松地从您的用户那里获得一个。启动 TaskMgr.exe,进程选项卡,在仍然显示崩溃对话框的同时选择被轰炸的程序。右键单击它并创建转储文件。
To make this smooth, you really want to automate this procedure. You'll find hints in my answer in this thread.
为了使这一切顺利,您确实希望自动化此过程。你会在这个线程的我的回答中找到提示。
回答by Permaquid
If you have a minidump, open it in Visual Studio, set MODPATH to the appropriate folders with the original binaries and PDBs, and tell it to "run". You may also need to tell it to load symbols from the Microsoft symbol servers. It will display the call stack at the error location. If you try to look at the source code for a particular stack location, it may ask you where the source is; if so, select the appropriate source folder. MODPATH is set in the debug command-line properties for the "project" that has the name of the minidump file.
如果您有一个小型转储,请在 Visual Studio 中打开它,将 MODPATH 设置为包含原始二进制文件和 PDB 的相应文件夹,并告诉它“运行”。您可能还需要告诉它从 Microsoft 符号服务器加载符号。它将在错误位置显示调用堆栈。如果您尝试查看特定堆栈位置的源代码,它可能会问您源代码在哪里;如果是,请选择适当的源文件夹。MODPATH 在具有小型转储文件名称的“项目”的调试命令行属性中设置。
回答by std''OrgnlDave
I know this thread is very old, but this was a top Google response, so I wanted to add my $.02.
我知道这个帖子很旧,但这是谷歌的顶级回复,所以我想添加我的 $.02。
Although a mini-dump is most helpful, as long as you have compiled your code with symbols enabled (just send the file without the .pdb, and keep the .pdb!) you can look up what line this was using the MSVC Debugger or Windows Debugger. MSN article on that:
尽管小型转储最有帮助,但只要您在启用符号的情况下编译了代码(只需发送不带 .pdb 的文件,并保留 .pdb!),您就可以使用 MSVC 调试器查找这是哪一行,或者Windows 调试器。MSN 上的文章:
回答by Dan Story
Source code information isn't preserved in compiled C++ code, unlike in runtime-based metadata-aware languages (such as .NET or Java). The PDB file is a symbol index which can help a debugger map compiled code backwards to source, but it has to be done during program execution, not from a crash dump. Even with a PDB, Release-compiled code is subject to a number of optimizations that can prevent the debugger from identifying the source code.
与基于运行时的元数据感知语言(例如 .NET 或 Java)不同,源代码信息不会保留在编译的 C++ 代码中。PDB 文件是一个符号索引,它可以帮助调试器将编译后的代码向后映射到源代码,但它必须在程序执行期间完成,而不是从故障转储中完成。即使使用 PDB,发布编译的代码也会受到许多优化的影响,这些优化可能会阻止调试器识别源代码。
Debugging problems which only manifest on end-user machines is usually a matter of careful state logging and a lot of detail-oriented time and effort combing over the source. Depending on your relationship with the user (for example, if you're internal corporate IT development), you may be able to make a virtual machine image of the user's machine and use it for debugging, which can help speed the process tremendously by precisely replicating the installed software and standard running processes on the user's workstation.
仅在最终用户机器上出现的调试问题通常是仔细的状态记录和大量面向细节的时间和精力来梳理源的问题。根据您与用户的关系(例如,如果您是公司内部的 IT 开发人员),您可以制作用户机器的虚拟机映像并将其用于调试,这可以通过精确地帮助极大地加快进程在用户的工作站上复制已安装的软件和标准运行过程。