分析Windows中的崩溃:错误消息告诉我们什么?

时间:2009-08-23 18:40:30

标签: c++ windows debugging assembly 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.

我的问题是,这些东西意味着什么,我将如何使用这些来调试我的程序?这是我目前所知的:异常代码描述了错误,而0xc0000005是内存访问冲突(试图访问它不拥有的内存)。我特别想知道以下内容:

  1. 故障偏移是什么意思?这是表示文件中发生错误的位置,还是表示发生错误的程序集“line”?知道了故障偏移,我如何使用像OllyDbg这样的程序来查找导致错误的相应汇编代码?或者 - 甚至更好 - 是否可以(轻松)确定C ++源代码中的哪一行代码导致此错误?
  2. 很明显,时间戳对应于崩溃时的32位UNIX时间,但64位应用程序的启动时间是什么意思?如果时间戳是32,为什么它会是64位?
  3. 请注意,我主要是一名C ++程序员,所以虽然我对汇编有所了解,但我对它的了解非常有限。此外,这确实不是一个需要修复的严重问题(并且鉴于程序的性质也不容易复制),我只是以此为借口来了解这些错误消息的含义。我在网上找到的关于这些崩溃日志的大部分信息通常都是针对最终用户的,所以他们没有帮助我(作为程序员)。

    提前致谢

5 个答案:

答案 0 :(得分:17)

64位时间戳是自1601年1月1日(UTC)以100纳秒间隔创建应用程序主线程的时间(这称为FILETIME)。 32位时间戳确实是time_t格式(它告诉模块创建的时间并存储在模块的标题中)。

我会说0x0002d160是模块加载地址的偏移量(绝对地址似乎太低)。启动Visual Studio,启动调试器,查看“模块”调试窗口。你的exe文件应该列在那里。找到加载模块的地址,将0x0002d160添加到该地址,然后查看结果地址处的反汇编。 Visual Studio显示与程序集混合的源代码,您应该没有问题找出导致问题的源代码行。

答案 1 :(得分:7)

您可以使用此信息进行事后调查。

有用的信息位是异常代码0xc0000005,在这种情况下只是意味着访问冲突。所以你取消引用null或者你没有的其他内存。

我怀疑,错误偏移是你的DLL加载到内存中的偏移量,所以理论上你可以将它添加到你的基地址并找到有问题的代码,但我不确定。

调试它的最佳选择是在下次发生这种情况时在调试器中捕获它。您可以使用Image File Execution Optionsdebugger中自动运行您的应用。确保您已准备好符号(如果您当前正在使用RELEASE,请考虑构建DEBUG。)

答案 2 :(得分:6)

调试上帝John Robbins构建了一个名为CrashFinder的小工具来帮助解决这样的情况: https://www.wintellect.com/crashfinder-2-8-yes-native-code-still-lives/

为您向公众发布的每个版本保存PDB总是一个好主意(这听起来像是一个私有使用的工具,但最好保留PDB符号以获得最新版本)。

答案 3 :(得分:1)

看起来这里仍然没有好的答案,如果崩溃发生在开发环境之外会怎样。 我认为off set是汇编代码崩溃的地址。 但是你需要知道那个dll的汇编代码的起点在哪里。或者您可能不需要知道起始地址,因为您可以使用组装工具打开dll,并通过将偏移量添加到起始地址来查找汇编代码

答案 4 :(得分:0)

我的程序 CrashExplorer 将使用故障偏移帮助分析此类崩溃:

它将使用 Visual Studio 生成的地图和列表文件: 映射文件列出了程序的所有函数和地址。列表文件将源代码映射到每个翻译单元的汇编代码。