代码之家  ›  专栏  ›  技术社区  ›  GRB

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

  •  25
  • GRB  · 技术社区  · 15 年前

    我为个人使用的一个小实用工具(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.
    

    我的问题是,这些东西都是什么意思,我如何使用它们来调试我的程序?这就是我目前所知道的:异常代码描述了错误,而0xc000005是内存访问冲突(试图访问它不拥有的内存)。我特别想了解更多关于以下方面的信息:

    1. 故障偏移是什么意思?这是表示发生错误的文件中的位置,还是表示发生错误的程序集“行”?知道故障偏移量后,如何使用Ollydbg这样的程序查找导致错误的相应程序集代码?或者——甚至更好——是否可以(很容易)确定C++源代码中的哪一行导致了这个错误?
    2. 很明显,时间戳对应于崩溃时的32位UNIX时间,但是64位应用程序启动时间意味着什么?如果时间戳是32,为什么它是64位?

    请注意,我主要是C++程序员,所以当我知道有关汇编的一些东西时,我对它的了解非常有限。此外,这确实不是一个需要修复的严重问题(而且也不容易复制,考虑到程序的性质),我只是将它更多地用作了解这些错误消息意味着什么的借口。我在网上找到的关于这些崩溃日志的大多数信息通常都是针对最终用户的,所以它们对我(作为程序员)没有太大帮助。

    提前谢谢

    4 回复  |  直到 7 年前
        1
  •  17
  •   avakar    15 年前

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

    我想说,0x0002d160是模块加载地址的偏移量(对于绝对地址来说,它似乎太低了)。启动Visual Studio,启动调试器,查看“模块”调试窗口。您的exe文件应该列在那里。找到加载模块的地址,将0x0002D160添加到该地址,并查看结果地址处的反汇编。Visual Studio显示的源代码与程序集混合在一起,您应该可以毫无问题地确定是什么源代码行导致了该问题。

        2
  •  7
  •   i_am_jorf    15 年前

    你用这些信息做验尸工作的能力不多。

    有用的信息位是异常代码0xC0000005,在这种情况下,它只是表示访问冲突。因此,您取消了空值或其他一些您不拥有的内存。

    我怀疑,fault offset是加载到内存中的dll的偏移量,因此理论上可以将其添加到基地址并找到有问题的代码,但我不确定。

    调试此项的最佳选择是下次在调试器中捕获它。你可以使用 Image File Execution Options debugger .确保您已经准备好了符号(如果您当前正在使用版本,请考虑构建调试)。

        3
  •  6
  •   ChrisN    7 年前

    调试上帝约翰·罗宾斯构建了一个叫做故障查找器的小工具来帮助处理这样的情况: https://www.wintellect.com/crashfinder-2-8-yes-native-code-still-lives/

    保存发布给公众的每个构建的PDB始终是一个好主意(这听起来像是一个仅在私有环境中使用的工具,但最好保留PDB符号以用于最新的构建)。

        4
  •  1
  •   Tony    10 年前

    看起来这里仍然没有很好的答案,如果崩溃发生在开发环境之外怎么办? 我认为偏移集是汇编代码崩溃的地址。 但您需要知道该dll的程序集代码的起始位置。或者您可能不需要知道起始地址,因为您可以使用汇编工具打开dll,并通过向起始地址添加偏移量来查找汇编代码。