我发现浮点数模型/错误问题相当令人困惑。这是我不熟悉的领域,我也不是低级C/asm程序员,所以我希望能得到一些建议。
我有一个使用VS2012(VC11)构建的较大的C++应用程序,并配置为抛出浮点异常(更准确地说,允许C++运行时和/或硬件抛出fp-exceptions) - 并且它在发布(优化)版本中抛出了很多异常,但在调试版本中没有。我认为这是由于优化和可能的浮点模型引起的(尽管编译器/fp:precise开关设置了发行版和调试版构建)。
我的第一个问题涉及管理应用程序的调试。我想控制fp-exceptions的抛出位置和屏蔽位置。这是必要的,因为我正在调试(经过优化的)发行版构建(其中发生了fp-exceptions) - 我想在某些函数中禁用fp-exceptions,在那里我检测到问题,以便我可以定位新的FP问题。但是我对使用_controlfp_s来完成此操作(可以正常工作)和编译器(和#pragma float_control)开关“/fp:except”之间的差异感到困惑(似乎没有任何影响)。这两种机制之间的区别是什么?它们是否应该对fp exceptions产生相同的影响?
其次,我收到了许多“浮点数堆栈检查”异常 - 其中一个异常似乎是在调用GDI+ dll时抛出的。在网上搜索时,关于此异常的少数提及似乎表明这是由于编译器错误引起的。一般情况下是这样吗?如果是这样,我该如何解决问题?最好是为问题函数禁用编译器优化,还是仅针对代码中存在的问题区域禁用fp-exceptions(如果没有返回坏的浮点数值的话)?例如,在引发此异常的GDI+调用(GraphicsPath :: GetPointCount)中,实际返回的整数值似乎是正确的。目前,我正在使用_controlfp_s直接在GDI+调用之前禁用fp-exceptions - 然后再次使用_controlfp_s直接在调用之后重新启用异常。
最后,我的应用程序确实进行了很多浮点数计算,并且需要具有鲁棒性和可靠性,但不一定需要非常准确。该应用程序的性质是,浮点值通常表示概率,因此本质上有些不精确。但是,我希望捕获任何纯逻辑错误,例如除以零。对于此情况,哪种浮点模型最好?目前我正在使用以下方法:
- 使用 _controlfp_s 和 SIGFPE 信号处理程序捕获所有浮点异常(即 EM_OVERFLOW | EM_UNDERFLOW | EM_ZERODIVIDE | EM_DENORMAL | EM_INVALID),
- 启用 denormals-are-zero (DAZ) 和 flush-to-zero (FTZ) (即 _MM_SET_FLUSH_ZERO_MODE(_MM_DENORMALS_ZERO_ON)),并且
- 使用默认的VC11编译器设置/fp:precise,未指定/fp:except。
这是最好的模型吗?
谢谢和问候!
try
/catch
或栈展开。这些也是异常,但其行为与C++异常不同。 - Ben Voigt