gpt4 book ai didi

c++ - 启用浮点异常的浮点堆栈处理

转载 作者:塔克拉玛干 更新时间:2023-11-02 23:42:14 25 4
gpt4 key购买 nike

我遇到了在 Visual Studio 2005 中打开浮点异常的问题。如果我有这样的代码:

  double d = 0.0;
double d2 = 3.0;
double d3 = d2/d;

如果我注册一个 SEH 处理程序例程,那么我可以轻松地将除零转换为 C++ 异常并捕获它。到目前为止一切顺利。

但是,当我这样做时,第一个操作数(上例中的 0.0)留在 FPU 寄存器堆栈中。如果我这样做八次,那么从那时起,我将开始在每个浮点操作中得到一个浮点堆栈检查异常。

我可以使用 __asm block 来执行 FSTP 来处理这个问题,从而将杂散值从堆栈中弹出,一切都很好。

然而,这让我很担心,因为我还没有在任何地方看到这个讨论。我如何确定应该弹出的值的数量?在异常发生时弹出堆栈上的所有内容是否安全?在这方面是否有推荐的最佳实践?

谢谢!

最佳答案

虽然我也找不到任何东西,但我可以就可能的答案给出一些解释:

ABI 定义在调用函数时堆栈应该为空,并且在退出时堆栈应该再次为空,除非返回的是浮点值,此时它将是堆栈中的唯一项。

由于异常处理程序必须能够返回到任何位置,因此某些条件必须适用于这些位置。这里的问题是,堆栈展开器是否知 Prop 有 catch() 的函数的 FPU 堆栈?答案很可能是否定的,因为创建具有固定属性的合适返回点比在展开中包含完整的 FPU 堆栈更容易和更快。

这会导致您的问题 - 通常引发异常会让编译器处理 FPU 为空,但在 SEH 处理程序中,编译器不知道它导致进入另一个函数,因此无法处理以防万一。 (除了它再次慢得可怕)

这意味着 FPU 堆栈在返回时最有可能处于其“一致”状态,这意味着您可能需要等效于 EMMS 指令。

为什么是 EMMS?好吧,除非它不受支持,否则它会执行以下操作:

  • 清除堆栈(修复所有剩余的浮点参数)
  • 清除堆栈标签(这修复了从支持 MMX 的函数退出时无法使用的堆栈)

如果您想支持 Pentium 1 或更差的处理器,您当然可以围绕 EMMS 使用 if() 并使用其他东西代替。

当然不能保证,但我希望我充分解释了可能答案的原因。

关于c++ - 启用浮点异常的浮点堆栈处理,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/1528359/

25 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com