gpt4 book ai didi

c++ fmod 为 fmod(0.0,1.0) 返回 NaN

转载 作者:行者123 更新时间:2023-11-30 01:43:31 29 4
gpt4 key购买 nike

我遇到了一个非常奇怪的情况:在我正在开发的多线程应用程序中,在某个代码点 fmod(x,y) 返回 -1.#IND00double x = 0.0 double y = 1.0。当然,我仔细检查了 xy 的值。更奇怪的是,如果我在 f=fmod(x,y); 行之前添加一个虚拟测试代码行 f=fmod(0.0,1.0); 然后fmod(x,y) 按预期返回 0.0

该应用程序是使用多线程运行时库构建的。 (VS2005) 可能是什么原因?

编辑 1:经过数小时的进一步研究,我发现它与 FPU 状态寄存器有关。当设置零除法异常标志时,它返回 -1。#IND00 否则返回正确的 0.0 值。我仍然不知道这里发生了什么。我的代码没有弄乱那个 FPU 状态寄存器,但它是关于一个插件的,所以我无法控制插件主机在做什么。但是,即使设置了零除法异常标志,为什么这里会有所不同,因为 fmod denom 值 = 1.0。这是 fmod 实现中的错误吗?有人听说过这样的错误吗?这让我抓狂。

编辑 2:我很确定这是 VS2005 中 CRT 库中 64 位 fmod 实现中的错误。当 FPU 状态寄存器 DivByZero 标志在调用 fmod 时已经出现,这会给出错误的结果。我很想通过一些测试代码来 100% 证明这一点,但我不能使用 VS2005 对 x64 进行内联汇编,以便用 FPU 强制除以零,这将设置该标志,然后我会调用 fmod。

最佳答案

我可以确认这是 VS2005 CRT 64 位 fmod 实现中的错误。很容易重复:确保在调用 z=fmod(x,y) 之前引发 FPU 中的 DivByZero 标志,其中 x=0.0 和 y=1.0,那么 z 将为 NaN,这当然是错误的。

所以这与多线程无关,也与内存损坏无关。这只是 CRT 库中的一个错误。

我使用 VirtualAlloc 制作了一个小测试应用程序以拥有一些可执行内存,我将代码字节放入其中以在 FPU 中进行除以零,以便提高 FPU DivByZero 标志。 (VS2005 不能内联 64 位汇编代码,因此 exe ram 技巧)然后我执行上面提到的 fmod 函数调用,实际上 z 显示为 -1.#IND00 = NaN。在调试器中仔细检查所有步骤。 QED.

我很惊讶我在 www 上找不到关于这个 CRT 错误的任何信息。我是第一个发现这个 CRT 错误的人吗?

无论如何,问题已经得到解答。结论:我将为 fmod 使用替代实现。

PS:如果有人想重复测试,这里是我用来在 FPU 中强制提升 DivByZero 标志的 x86 代码字节:

0xD9,0xEE = fldz
0xD9,0xE8 = fld1
0xD8,0xF1 = fdiv ST(0),ST(1)
0xDD,0xD8 = fstp ST(0) = pop stack
0xDD,0xD8 = fstp ST(0) = pop stack
0xC3 = ret

关于c++ fmod 为 fmod(0.0,1.0) 返回 NaN,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/37615096/

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