C++ 分析 Windows 中的崩溃:错误消息告诉我们什么?
声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow
原文地址: http://stackoverflow.com/questions/1319234/
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
Analyzing a crash in Windows: what does the error message tell us?
提问by GRB
A small utility of mine that I made for personal use (written in C++) crashed randomly yesterday (I've used it roughly 100+ hours with no issues so far) and while I don't normally do this, I was feeling a bit adventurous and wanted to try and learn more about the problem. I decided to go into the Event Viewer and see what Windows had logged about the crash:
我为个人使用而制作的一个小工具(用 C++ 编写)昨天随机崩溃(我已经使用了大约 100 多个小时,到目前为止没有任何问题),虽然我通常不这样做,但我感觉有点喜欢冒险,想尝试更多地了解这个问题。我决定进入事件查看器并查看 Windows 记录的有关崩溃的信息:
Faulting application StraightToM.exe, version 0.0.0.0, time stamp 0x4a873d19
Faulting module name : StraightToM.exe, version 0.0.0.0, time stamp 0x4a873d19
Exception code : 0xc0000005
Fault offset : 0x0002d160,
Faulting process id: 0x17b4
Faulting application start time: time 0x01ca238d9e6b48b9.
My question is, what do each of these things mean, and how would I use these to debug my program? Here's what I know so far: exception code describes the error, and 0xc0000005 is a memory access violation (tried to access memory it didn't own). I'm specifically interested in knowing more about the following:
我的问题是,这些东西是什么意思,我将如何使用这些来调试我的程序?这是我目前所知道的:异常代码描述了错误,0xc0000005 是内存访问冲突(试图访问它不拥有的内存)。我特别有兴趣了解更多关于以下内容:
- What does the fault offset mean? Does that represent the location in the file where the error occured, or does it mean the assembly 'line' where the error occured? Knowing the fault offset, how would I use a program like OllyDbg to find the corresponding assembly code that caused the error? Or -- even better -- would it be possible to (easily) determine what line of code in the C++ source caused this error?
- It's obvious that the time stamp corresponds to the 32-bit UNIX time at the time of the crash, but what does the 64-bit application start time mean? Why would it be 64-bits if the time stamp is 32?
- 故障偏移是什么意思?这是否表示发生错误的文件中的位置,还是表示发生错误的程序集“行”?知道了故障偏移量,我该如何使用OllyDbg这样的程序来查找导致错误的相应汇编代码?或者——甚至更好——是否可以(轻松)确定 C++ 源代码中的哪一行代码导致了此错误?
- 很明显,时间戳对应的是崩溃时的 32 位 UNIX 时间,但是 64 位应用程序启动时间是什么意思呢?如果时间戳是 32,为什么会是 64 位?
Note that I'm primarily a C++ programmer, so while I know something about assembly, my knowledge of it is very limited. Additionally, this really isn't a serious problem that needs fixing (and is also not easily reproduced, given the nature of the program), I'm just using this more as an excuse to learn more about what these error messages mean. Most of the information about these crash logs that I've found online are usually aimed at the end-user, so they haven't helped me (as the programmer) very much.
请注意,我主要是一名 C++ 程序员,所以虽然我对汇编有所了解,但我对它的了解非常有限。此外,这确实不是一个需要修复的严重问题(鉴于程序的性质,也不容易重现),我只是以此为借口更多地了解这些错误消息的含义。我在网上找到的有关这些崩溃日志的大部分信息通常都是针对最终用户的,因此它们对我(作为程序员)并没有太大帮助。
Thanks in advance
提前致谢
采纳答案by avakar
The 64-bit time stamp is the time application's primary thread was created in 100-nanosecond intervals since January 1, 1601 (UTC) (this is known as FILETIME
). The 32-bit timestamp is indeed in time_t
format (it tells the time the module was created and is stored in the module's header).
64 位时间戳是自 1601 年 1 月 1 日 (UTC) 起以 100 纳秒为间隔创建应用程序主线程的时间(这称为FILETIME
)。32 位时间戳确实是time_t
格式(它告诉模块创建的时间并存储在模块的标题中)。
I'd say 0x0002d160 is an offset from the module's load address (it seems too low for an absolute address). Fire up Visual Studio, start the debugger, take a look at the "modules" debug window. Your exe file should be listed there. Find the address where the module is loaded, add 0x0002d160 to that address and take a look at the disassembly at the resulting address. Visual Studio shows source code intermixed with the assembly, you should have no problem figuring out what source line caused the problem.
我会说 0x0002d160 是模块加载地址的偏移量(对于绝对地址来说似乎太低了)。启动 Visual Studio,启动调试器,查看“模块”调试窗口。您的 exe 文件应该列在那里。找到加载模块的地址,在该地址上添加0x0002d160,然后查看结果地址处的反汇编。Visual Studio 显示与程序集混合的源代码,您应该可以轻松找出导致问题的源代码行。
回答by i_am_jorf
There isn't much you're going to be able to do postmortem with this information.
使用这些信息,您将无法进行事后分析。
The useful bit of information is the exception code, 0xc0000005, which in this case just means an access violation. So you dereferenced null or some other bit of memory you didn't own.
有用的信息是异常代码 0xc0000005,在这种情况下,它仅表示访问冲突。因此,您取消了对 null 或其他一些您不拥有的内存的引用。
Fault offset, I suspect, is the offset from where your DLL was loaded into memory, so you could in theory add it to your base address and find the offending code, but I'm not sure.
我怀疑,故障偏移量是从您的 DLL 加载到内存的位置的偏移量,因此理论上您可以将其添加到您的基地址并找到有问题的代码,但我不确定。
Your best bet for debugging this is to catch it in the debugger the next time this happens. You can use Image File Execution Optionsto run your app automatically in the debugger. Make sure you have symbols ready (consider building DEBUG if you're currently using RELEASE).
调试它的最佳选择是在下次发生这种情况时在调试器中捕获它。您可以使用Image File Execution Options在调试器中自动运行您的应用程序。确保您已准备好符号(如果您当前正在使用 RELEASE,请考虑构建 DEBUG)。
回答by Kim Gr?sman
Debugging god John Robbins built a little tool called CrashFinder to help with situations like this: https://www.wintellect.com/crashfinder-2-8-yes-native-code-still-lives/
调试大神 John Robbins 构建了一个名为 CrashFinder 的小工具来帮助处理这样的情况:https://www.wintellect.com/crashfinder-2-8-yes-native-code-still-lives/
It's always a good idea to save PDBs for every build you release to the public (this sounds like a tool you only use in private, but it might be a good idea to keep the PDB symbols around for the latest build).
为您向公众发布的每个构建保存 PDB 始终是一个好主意(这听起来像是您只在私人使用的工具,但为最新构建保留 PDB 符号可能是个好主意)。
回答by Tony
looks like there is still no good answer here, what if the crash happens outside the development environment. I think off set is the address where the assembly code crash. But you need to know where the start of the assembly code of that dll is. or maybe you don't need to know the start address, because you can use assembly tool to open dll, and find the assembly code by adding the offset to start address
看起来这里仍然没有好的答案,如果崩溃发生在开发环境之外怎么办。我认为偏移是汇编代码崩溃的地址。但是你需要知道那个dll的汇编代码的开头在哪里。或者你可能不需要知道起始地址,因为你可以使用汇编工具打开dll,通过将偏移量添加到起始地址来找到汇编代码