2014-12-04 46 views
8

对于我而言,我正在努力拼搏(但徒劳无益)与异常掩码。德尔福中的掩蔽例外

我开发了一个应用程序,可以对数十万条记录进行繁重的浮点计算。显然,代码必须能够处理异常,尤其是那些与浮点计算相关的异常:溢出,ZeroDivide等。

在Windows 7(32位或64位)下,应用程序在许多不同类型的处理器发生错误时,条件得到正确处理,引发异常并丢弃记录。

不幸的是,当我启动应用程序的目的地运行的时候,问题就开始了:在带有Intel Xeon E5-2640 v2 CPU和Windows Server 2003 R2的专用服务器上。这里不会出现异常:带有错误的记录不会被丢弃,因此结果受到这些机器描述的数值的污染+INF-INF

的问题是,在服务器上的错误掩蔽的默认设置是从那些我们在Windows 7中特别找不同,默认情况下调用服务器上的程序GetExceptionMask我发现exZeroDivide如果在Windows调用GetExceptionMask而7这个例外没有被掩盖。结果就是我所说的:在服务器上运行应用程序,这些异常不会引发,而是由处理器处理,返回极端值并“污染”数值。

好的,不要惊慌,我说,你只需调用(即在初始化部分)SetExceptionMask,不包括exZeroDivide,但不起作用。或者更好的是,虽然在调用SetExceptionMask之后,异常exZeroDivide不再被屏蔽,当执行带有浮点计算的代码时TArithmeticExceptionMask返回的集合GetExceptionMask仍然包含exZeroDivide,所以如果发生错误,则不会引发异常。

任何人都可以告诉我什么是正确的方式叫SetExceptionMask

这就是为什么屏蔽默认值可能与计算机和另一台计算机不同的原因?操作系统或处理器的类型?

谢谢。

+2

这是一个很好的描述,但你可以发布一些生成异常的示例代码,以及一个示例来展示你如何处理屏蔽?这将使我们更容易帮助您找到解决方案。 :) – 2014-12-04 01:18:20

+0

我同意,很难说,没有看到你是如何做到这一点。我建议开始一个全新的测试应用程序,以复制这种行为,并与我们分享该代码。 – 2014-12-04 01:24:46

+1

听起来好像有什么东西被注入到Server 2003的进程中 - 病毒检查器,全局钩子,其他系统监视工具? - 用不正确的值设置FP标志字。 – 2014-12-04 01:48:16

回答

4

这通常是因为您正在调用清除掩码的第三方代码。它可能是一个你有意使用的图书馆,但更有可能的是你并没有特别注意调用。一个常见的例子是打印机驱动程序。这些是改变浮点控制标志的臭名昭着的。

下一步是识别更改控制标志的那部分代码。我建议你添加调试跟踪日志记录。打电话给OutputDebugString就足够了,但是您最好使用更高级的日志记录库。在程序执行时记录控制标志的状态。在找到罪魁祸首之前,您需要几个周期的添加日志记录调用,运行,读取日志。一旦找到更改标志的外部代码,请确保在外部代码执行后恢复它们。

这是一个棘手的领域,我害怕。要做对并不容易。外部代码有时会与控制标志一起快速松动,就好像该代码是存在的唯一代码一样。 Delphi RTL在处理控制标志方面也不是最好的。例如,Set8087CW不是线程安全的也许不是众所周知的。

我个人经历了与我自己的浮点应用程序的斗争。但你应该能够解决这些问题。祝你好运!