Jua*_*ura 8 delphi exception-handling floating-point-exceptions
几天来,我一直在用异常面具努力(但徒劳无功).
我开发了一个应用程序,可以对数十万条记录进行大量浮点计算.显然,代码必须能够处理异常,尤其是与浮点计算相关的异常:溢出,ZeroDivide等.
应用程序在具有许多不同类型处理器的Windows 7(32位或64位)下正确运行,如果发生错误,则正确处理条件,引发异常并丢弃记录.
不幸的是,当我启动应用程序时,问题就出现了:在具有Intel Xeon E5-2640 v2 CPU和Windows Server 2003 R2的专用服务器上.这里异常没有提出:有错误的记录不会被与机器描绘这些数值丢弃,所以结果被污染+INF或-INF.
问题是在服务器上,错误屏蔽的默认设置与我们在Windows 7中找到的设置不同.特别是,GetExceptionMask默认情况下exZeroDivide调用服务器上的过程我发现,如果GetExceptionMask在Windows 7上调用此异常未被屏蔽.结果就是我说的:在服务器上运行应用程序时,这些异常不会引发,而是由处理器返回极值和"污染"数值来处理.
好吧,不要惊慌,我说,你只是打电话(即在初始化部分)SetExceptionMask排除exZeroDivide,但不起作用.或者更好,虽然刚刚调用SetExceptionMask异常 后exZeroDivide不再屏蔽,但是当执行具有浮点计算的代码时,TArithmeticExceptionMask返回的集GetExceptionMask仍然包含exZeroDivide,因此如果发生错误,则不会引发异常.
有谁能告诉我什么是正确的打电话方式SetExceptionMask?
屏蔽默认值可能与计算机和另一台计算机不同的原因是什么?操作系统或处理器类型?
谢谢.
造成这种情况的通常原因是您正在调用清除掩码的第三方代码。它可能是您有意使用的库,但更有可能是您没有特别意识到调用的库。一个常见的例子是打印机驱动程序。这些因更改浮点控制标志而臭名昭著。
下一步是识别更改控制标志的代码部分。我建议您添加调试跟踪日志记录。调用OutputDebugString就足够了,但是您最好使用更高级的日志记录库。程序执行时记录控制标志的状态。在找到罪魁祸首之前,您需要几个周期的添加日志记录调用、运行、读取日志。一旦找到更改标志的外部代码,请确保在该外部代码执行后恢复它们。
恐怕这是一个棘手的领域。要做到正确并不容易。外部代码有时确实会快速而宽松地使用控制标志,就好像该代码是唯一存在的代码一样。Delphi RTL 在处理控制标志方面也不是最好的。Set8087CW例如,人们可能并不知道它不是线程安全的。
我个人经历过您与我自己的浮点应用程序的斗争。但你应该能够解决此类问题。祝你好运!