【问题标题】:Heisenbug: WinApi program crashes on some computersHeisenbug:WinApi 程序在某些计算机上崩溃
【发布时间】:2010-09-13 00:36:39
【问题描述】:

请帮忙!我真的束手无策。 我的程序是一个小小的个人笔记管理器(谷歌为“cintanotes”)。 在某些计算机上(当然我不拥有它们),它在启动后立即崩溃并出现未处理的异常。 这些计算机没有什么特别之处,只是它们往往具有 AMD CPU。

环境:Windows XP、Visual C++ 2005/2008、原始 WinApi。

这是关于这个“黑森虫”的肯定:

1) 崩溃仅发生在 Release 版本中。

2) 一旦我删除所有与 GDI 相关的内容,崩溃就会消失。

3) BoundChecker 没有任何抱怨。

4) 编写日志显示崩溃发生在声明局部 int 变量时!怎么可能?内存损坏?

任何想法将不胜感激!

更新:我已经设法在“故障”PC 上调试了该应用程序。结果:

“CintaNotes.exe 中 0x0044a26a 处未处理的异常:0xC000001D:非法指令。”

代码中断

0044A26A cvtsi2sd xmm1,dword ptr [esp+14h]

看来问题出在“代码生成/启用增强指令集”编译器选项中。它被设置为“/arch:SSE2”并且在不支持 SSE2 的机器上崩溃。我已将此选项设置为“未设置”,并且该错误消失了。呼!

非常感谢大家的帮助!!

【问题讨论】:

  • 看起来 Goldenmean 最接近答案。

标签: c++ debugging winapi crash gdi


【解决方案1】:

4) 写日志显示崩溃发生在声明局部 int 变量时!怎么可能?内存损坏?

可执行文件/程序集中的底层代码是什么? int 的声明根本不是代码,因此不会崩溃。您是否以某种方式初始化 int?

要查看发生崩溃的代码,您应该执行所谓的事后分析。

Windows 错误报告

如果你想分析崩溃,你应该得到一个崩溃转储。一种选择是注册 Windows 错误报告 - 需要一些钱(您需要一个数字代码签名 ID)和一些表格填写。更多信息请访问https://winqual.microsoft.com/

直接从客户那里获取用于 WER 的故障转储

另一种选择是与遇到崩溃的某些用户取得联系,并直接从他那里获得用于 WER 的崩溃转储。用户可以在将崩溃发送给 Microsoft 之前单击技术详细信息来执行此操作 - 可以在此处检查崩溃转储文件的位置。

您自己的小型转储

另一种选择是注册您自己的异常处理程序,处理异常并在您希望的任何地方编写一个小型转储。详细说明见Code Project Post-Mortem Debugging Your Application with Minidumps and Visual Studio .NET article

【讨论】:

  • 确保您在 RELEASE(以及调试)模式下为您的应用程序构建调试信息(PDB 文件)。确保为每个已发布版本保留一组 PDB,以便可以将它们与转储一起使用。也许使用本地符号服务器。投票给 Suma 回答 - 这是正确的!
  • 谢谢,我将尝试使用 minidump 的最后一个想法。不幸的是我不习惯低级调试,所以我需要阅读更多关于此的内容......
【解决方案2】:

所以配置为DEBUG配置时不会崩溃?与 RELEASE 配置有很多不同之处: 1.) 全局变量的初始化 2.) 生成的实际机器代码等。

因此,第一步是找出与 DEBUG 模式相比,RELEASE 模式下每个参数的确切设置。

-AD

【讨论】:

    【解决方案3】:

    1) 崩溃仅发生在 Release 版本中。

    这通常表明您依赖于某些无法保证的行为,但在调试版本中恰好是正确的。例如,如果您忘记初始化变量,或访问越界数组。确保您已打开所有编译器检查 (/RTCsuc)。还要检查依赖函数参数的评估顺序(不能保证)。

    2) 一旦我删除所有与 GDI 相关的内容,崩溃就会消失。

    也许这暗示你在 GDI 相关的东西上做错了什么?例如,您是否在释放 HANDLE 后使用它们?

    【讨论】:

    • 我确实遇到了 HFONT 句柄的一个问题,但在 BoundsChecker 向我指出后就解决了。但不幸的是,该错误并未受到此更改的影响。
    【解决方案4】:

    下载Debugging tools for Windows 包。正确设置符号路径,然后在 WinDbg 下运行您的应用程序。在某些时候,它会因访问冲突而中断。然后你应该运行命令“!analyze -v”,它非常聪明,应该给你一个关于哪里出了问题的提示。

    【讨论】:

    • 我需要在有问题的机器上本地执行此操作吗?
    【解决方案5】:

    大多数 heisenbugs/仅发布错误是由于依赖于未初始化内存/过时指针/缓冲区结束读取的控制流,或竞争条件,或两者兼而有之。

    尝试覆盖您的分配器,以便它们在分配时将内存清零。问题是否会消失(或变得更具重现性?)

    写日志显示崩溃发生在声明局部 int 变量时!怎么可能?内存损坏?

    堆栈溢出! ;)

    【讨论】:

    • 感谢您的想法,我一定会朝这个方向进行调查
    【解决方案6】:

    4) 写日志显示崩溃发生在声明本地 int 变量时!怎么可能?内存损坏

    我发现许多“奇怪的崩溃”的原因是取消引用所述对象的成员函数中损坏的this

    【讨论】:

    • 您能否详细说明一下,“破这个”到底是什么?
    • Alex, broken this 就像...这样:string ps = new string;删除ps; ps->清除()。当您进入 clear() 时,您会看到损坏的 this
    【解决方案7】:

    崩溃说明了什么?访问冲突?例外 ?这将是解决此问题的进一步线索

    使用 PageHeap.exe 确保您没有先前的内存损坏

    确保没有堆栈溢出(CBig array[1000000])

    确保您没有未初始化的内存。

    此外,一旦您为进程生成调试符号(与创建调试版本不同),您还可以在调试器中运行发布版本。逐步检查您是否在调试器跟踪窗口中收到任何警告。

    【讨论】:

      【解决方案8】:

      "4) 写日志显示崩溃发生在声明局部 int 变量时!怎么可能?内存损坏?"

      这可能表明硬件实际上存在故障或被推得太紧。看看他们是否超频了他们的电脑。

      【讨论】:

      • 我认为情况并非如此。它发生在许多未超频的 PC 上。
      【解决方案9】:

      当我得到这种类型的东西时,我尝试通过 gimpels PC-Lint(静态代码分析)运行代码,因为它会检查不同类别的错误到 BoundsChecker。如果您使用的是 Boundschecker,请打开内存中毒选项。

      您提到了 AMD CPU。您是否调查过崩溃的机器上是否有类似的显卡/驱动程序版本和/或配置?它总是在这些机器上崩溃还是偶尔崩溃?也许在这些机器上运行系统信息工具,看看它们有什么共同点,

      【讨论】:

        【解决方案10】:

        对我来说,这听起来像是堆栈损坏。我最喜欢的追踪工具是IDA Pro。当然,您没有访问用户机器的权限。

        一些内存检查器很难发现堆栈损坏(如果确实如此)。我认为最可靠的方法是运行时分析。

        这也可能是由于异常路径中的损坏,即使异常已被处理。您是否在打开“捕获第一机会异常”的情况下进行调试?你应该尽可能长。在许多情况下,它确实会在一段时间后变得烦人。

        您能否向这些用户发送您的应用程序的检查版本?查看Minidump 处理该异常并写出转储。然后使用WinDbg 进行调试。

        另一种方法是编写非常详细的日志。创建一个“记录每个操作”选项,并要求用户将其打开并将其发送给您。将内存转储到日志中。查看 MSDN 上的“_CrtDbgReport()”。

        祝你好运!

        编辑:

        回复您的评论:局部变量声明中的错误对我来说并不奇怪。我已经看到很多了。这通常是由于堆栈损坏。

        例如,堆栈上的某些变量可能会超出其边界。在那之后,所有的地狱都崩溃了。然后堆栈变量声明会引发随机内存错误、虚拟表损坏等。

        每当我看到这些内容很长一段时间后,我就不得不去 IDA Pro。 详细的运行时反汇编调试是我所知道的唯一真正可靠的东西。

        许多开发人员使用 WinDbg 进行此类分析。这就是为什么我也建议使用 Minidump。

        【讨论】:

        • 感谢您的所有想法。我已经写了一个日志,它指向一个 int 变量声明。我不是在开玩笑,是这样的代码: log
        【解决方案11】:

        试试 Rational (IBM) PurifyPlus。它捕获了许多 BoundsChecker 没有捕获的错误。

        【讨论】:

        猜你喜欢
        • 2018-07-27
        • 1970-01-01
        • 1970-01-01
        • 2013-11-26
        • 1970-01-01
        • 1970-01-01
        • 2012-12-13
        • 1970-01-01
        • 1970-01-01
        相关资源
        最近更新 更多