调试过程中出现算术下溢或上溢异常。

10

今天是奇怪行为的一天。

我们有一个使用Delphi 2007制作的Win32项目,它托管.NET运行时并调用.NET显示新窗体,作为过渡期的一部分。

最近我们开始在代码的似乎随机位置和点经历异常:算术溢出或下溢。

其中一个的堆栈跟踪看起来像这样:

at System.Windows.Forms.UnsafeNativeMethods.DispatchMessageW(MSG& msg)
at System.Windows.Forms.Application.ComponentManager.System.Windows.Forms.UnsafeNativeMethods.IMsoComponentManager.FPushMessageLoop(Int32 dwComponentID, Int32 reason, Int32 pvLoopData)
at System.Windows.Forms.Application.ThreadContext.RunMessageLoopInner(Int32 reason, ApplicationContext context)
at System.Windows.Forms.Application.ThreadContext.RunMessageLoop(Int32 reason, ApplicationContext context)
at System.Windows.Forms.Application.RunDialog(Form form)
at System.Windows.Forms.Form.ShowDialog(IWin32Window owner)
at System.Windows.Forms.Form.ShowDialog()
at Gatsoft.Gat.UI.Windows.Forms.Remanaging.RemanageForm.DelphiOpenInNewMode(String employeeCode, String departmentCode, DateTime date) in C:\Dev\VS.NET\Gatsoft\Gatsoft.Gat.UI.Windows\Forms\Remanaging\RemanageForm.Delphi.cs:line 67

在Visual Studio解决方案中,最外层的类库(即尽可能引入所有引用)已设置了一个特定的调试程序,针对Delphi项目输出进行了目标设置。这使我们能够从Visual Studio调试.NET代码,即使主要的程序大部分是用Delphi编写的。
问题只在从调试器运行时出现,如果我们直接运行exe文件(无论是通过资源管理器、快捷方式还是甚至在Visual Studio内使用Ctrl + F5),则不会出现此问题。
显然,机器上没有间谍软件(如此处所示)。
还有其他可以检查的事情吗?

编辑:看起来.NET调试器正在启用此SNaN标志,而Delphi调试器没有。我们需要进一步调查这个问题,但现在我会接受@Lorenzo Boccaccia的答案。

显然已解决

好的,看起来我们终于解决了这个问题。这个问题开始出现时没有连接调试器,对于我们的测试人员也是如此,因此我们不得不将问题优先考虑。

最终,我们发现了那些出现问题的机器上一个共同的问题,它们都是Dell Lattitude D620笔记本电脑,带有NVIDIA Quadro NVS 110M,并且使用了2006年早期的系统镜像中的旧驱动程序。

我在网上找到了一篇文章,但当我重新启动更新显示驱动程序时,我失去了它的URL,其中一个.NET服务崩溃,大多数情况下是在机器忙于在屏幕上执行某些操作时发生的。重现他的问题的一种方法是打开一个命令提示符到C:\并执行DIR /S以强制进行大量的屏幕更新,这将触发崩溃。

他也有一个NVIDIA视频卡。

我的机器上的问题大约每2-4次启动我们的程序就会出现一次,但在更新了视频驱动程序之后,我已经成功启动了123次而没有任何问题。(顺便说一下,我可以推荐AutoHotKey这样的工具)。

因此,看起来我们找到了罪魁祸首,是旧/有缺陷的NVIDIA驱动程序。

更新了这个问题,希望未来的某个人可以节省一些时间。

现在,请原谅我,我要去角落里哭泣。

倒霉啊!

我一定是招惹了麻烦。我刚发布上面的更新,一位同事的笔记本电脑就坏了,在更新视频驱动程序后。

不过,我相信这是我们应用程序之外的问题,所以现在只需要找出需要更新的具体内容就行了。


进一步的更新:好的,我的电脑现在显然已经修好了,但是我的同事的电脑还没有。到目前为止,我们已经更新了BIOS、芯片组驱动程序,目前XP的SP3正在传递中。

今晚将进行烤机测试,应用程序将在启动时保持开启状态,因为问题可能会在启动时出现,或者在第一次执行WinForms .NET代码时出现。这个应用程序主要是一个Delphi Win32应用程序,但它托管了.NET运行时,问题似乎与.NET代码有关。当我们“引导”.NET运行时时,问题可能会出现,或者当我们从Win32触发第一个.NET窗口时,问题也可能会出现。


统计数据显示,我现在可以发布这段代码了。在过去的一晚上中,该应用程序已经启动了3051次而没有出现错误,在更新视频驱动程序之前,它每2-4次就会崩溃。

被刺激并发现(!/?)

这个修复bug的过程感觉就像去看医生,以下是可能发生的对话:

Doc: Does this hurt?
Me: No...
Doc: What about now?

我已经检查并测试了这个应用程序,最终我认为我找到了我们做的某些事情引入了这个问题。

在我们的应用程序中,我们从 Delphi 2007 Win32 应用程序托管 .NET 运行时,在我们的粘合代码中,我们现在有以下代码 (已修改):

  rc := CorBindToRuntimeEx('v2.0.50727', 'wks',
  STARTUP_LOADER_OPTIMIZATION_MULTI_DOMAIN or STARTUP_CONCURRENT_GC,
  @clsid, @iid, UnkRuntimeEngine);

那两个常量原本是0,意思是选择默认值。这个更改在几个月前引入,这个问题在此后慢慢地困扰着我们。更改是为了鼓励ANTS分析器加载我们的Win32应用程序+托管.NET运行时来进行性能分析,并且我们当时引入的更改使其工作。此外,算术溢出/下溢的问题越来越严重,所以我打赌问题在更改后一段时间内没有出现,因此它没有归因于我们所做的任何更改。

另外,由于我们最初只在调试器中看到了这个问题,我们认为Visual Studio和/或Delphi出了问题。

无论如何,现在统计学上,在一个屏幕上通过Javascript反复触发滚动,然后在调用中726次成功启动应用程序,并且在那两个常量存在时17次崩溃了5次。

Doc: Does this hurt?

我们不要深究谁最初做出了那个更改。我相信罪犯想保持匿名...咳咳

2个回答

1

1

如果您在启动应用程序后附加调试器,错误是否仍然会发生?


这个问题很重要的原因是由调试器启动的进程使用特殊的“调试堆”。请参阅http://blogs.msdn.com/larryosterman/archive/2008/09/03/anatomy-of-a-heisenbug.aspx或http://msdn.microsoft.com/en-us/library/974tc9t1.aspx。 - Michael Ratanapintha
谢谢你们两个,我明天会检查。这确实是一个Heisenbug,而且还是一个随机的Heisenbug,因为在它再次出现之前,我可以进行几个调试周期。 - Lasse V. Karlsen
只有通过.NET调试器启动时,才会进行调试。 - Lasse V. Karlsen

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接