我开发了一个应用程序,可以对数十万条记录进行大量浮点计算.显然,代码必须能够处理异常,尤其是与浮点计算相关的异常:溢出,ZeroDivide等.
应用程序在具有许多不同类型处理器的Windows 7(32位或64位)下正确运行,如果发生错误,则正确处理条件,引发异常并丢弃记录.
不幸的是,当我启动应用程序时,问题就出现了:在具有Intel Xeon E5-2640 v2 cpu和Windows Server 2003 R2的专用服务器上.这里不会引发异常:不会丢弃有错误的记录,因此结果会受到机器描述INF或-INF的这些数值的影响.
问题是在服务器上,错误屏蔽的默认设置与我们在Windows 7中找到的设置不同.特别是,默认情况下在服务器上调用过程GetExceptionMask我发现exZeroDivide,而如果在Windows 7上调用GetExceptionMask,则此异常是没有蒙面.结果就是我所说的:在服务器上运行应用程序时,这些异常不会引发,而是由处理器返回极值和“污染”数值来处理.
好吧,不要惊慌,我说,你只是调用(即在初始化部分)SetExceptionMask,不包括exZeroDivide,但不起作用.或者更好,虽然在调用SetExceptionMask之后,异常exZeroDivide不再被屏蔽,当执行具有浮点计算的代码时,GetExceptionMask返回的集合TArithmeticExceptionMask仍包含exZeroDivide,因此如果发生错误,则不会引发异常.
谁能告诉我调用SetExceptionMask的正确方法是什么?
屏蔽默认值可能与计算机和另一台计算机不同的原因是什么?操作系统或处理器类型?
谢谢.
解决方法
下一步是确定更改控制标志的代码部分.我建议你添加调试跟踪日志记录.调用OutputDebugString就足够了,但是你可以使用更高级的日志库.在程序执行时记录控制标志的状态.在找到罪魁祸首之前,您需要几个周期来添加日志记录调用,运行,读取日志.找到更改标志的外部代码后,请确保在执行外部代码后恢复它们.
这是一个我很害怕的棘手问题.做起来并不容易.外部代码有时会使用控制标志快速松散地运行,就好像该代码是唯一存在的代码一样. Delphi RTL在处理控制标志方面也不是最好的.例如,Set8087CW不是线程安全的可能并不为人所知.
我个人经历过我自己的浮点应用程序的困难.但是你应该能够解决这些问题.祝好运!