调试期间出现算术下溢或者溢出异常
这是奇怪行为的一天。
我们有一个用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项目的输出。即使程序的大部分是用Delphi编写的,这也使我们能够从Visual Studio调试.NET代码。
该问题仅在从调试器运行时发生,而不是如果我们仅直接运行exe文件(通过资源管理器,快捷方式,甚至是Visual Studio中的Ctrl + F5键),则不会发生。
机器上显然没有间谍软件(由此暗示)。
我们还有其他可以检查的东西吗?
编辑:看起来.NET调试器正在启用此SNaN标志,而Delphi调试器则未启用。我们将不得不对此进行进一步调查,但是现在我将接受@Lorenzo Boccaccia的回答。
显然解决了
好的,看来我们终于解决了这个问题。对于我们的测试人员来说,在没有连接调试器的情况下就开始出现问题,因此我们必须优先解决问题。
最终,我们发现存在问题的机器是一个常见问题,它们是配备NVIDIA Quadro NVS 110M的Dell Lattitude D620笔记本电脑,该笔记本电脑的系统驱动程序中的旧驱动程序可用于配置笔记本电脑,最早可追溯到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次崩溃。
提议并发现(!/?)
修复错误的过程就像去看医生一样,随后进行了以下对话:
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次,调用中为0 ,在其中存在两个常量的情况下,它崩溃了17次中的5次。
Doc: Does this hurt?
而且,让我们先不谈谁进行了更改。我确定罪魁祸首想匿名...咳嗽
解决方案
回答
如果在启动应用程序后添加调试器,是否仍会发生错误?
回答
可以使用Signaling Nan支持来编译链接dll的调试版本,有关此问题的示例,请参见http://blogs.msdn.com/oldnewthing/archive/2008/07/02/8679191.aspx。
heisenbug是由未初始化的变量引起的,这里可能有一个链接的dll,它启用了cpu的snan功能,而忘记了在返回时将其禁用