为什么在 VxWorks 中给定大量数字时 strtod 会冻结?

Why does strtod freeze up when given large numbers in VxWorks?

在 VxSim 中,当我 运行 strtod("1E1000000", 0)(在 stdlib.h 中)它 运行 非常快(和 returns 1),而 strtod("1E1000000000000000000000000000", 0) 大约需要 20 秒,然后 returns 1。有时它总是很快,但 returns 非零值,然后按 ctrl-c 并重置 shell 会再次变慢。

为什么会这样?在其他操作系统中,两者都接近瞬时。

当你 运行:

strtod("10", 0)
strtod("10", 0)
strtod("10", 0)
strtod("10", 0)
strtod("10", 0)
strtod("10", 0)
strtod("10", 0)
strtod("10", 0)

最后一个给你:

值 = 1615516944 = 0x604ad510

我在硬件上测试了这个,但没有出现,所以这可能是 VxSim 中的一个错误。

另外,编译它也不会给你那个错误。仅当您将这些手动键入 VxWorks 命令行并在那里 运行 它们时才会出现。

这两个数字都远高于可表示的最大有限 IEEE 754 双精度值,约为 1.79769e+308。几乎没有理由将“1E1000000000000000000000000000”转换为双精度,尽管在安全敏感的上下文中,当允许攻击者输入旨在转换为浮点数的字符串时,这可能是一次不错的拒绝服务攻击后来,转换花费的时间比程序员想象的要多。

由于几乎没有理由将“1E1000000000000000000000000000”转换为双精度,您尝试的其中一个实现没有实现识别这种情况的优化,实际上做了很多计算(*)在意识到这个数字比无论如何可以表示的数字大得多之前。而其他更智能的实现会及早检测到十进制指数太大,最终结果只能是 +inf,并且会提前检测到 return。

要寻找的另一个有趣的输入是“0.000<10000 个零>1E10000”。在这种情况下,不正确的“优化”版本可能会错误 return +inf

还有一个有趣的极端情况是“0E1000000000000000000”,除了 0.0.

之外,它不应该 return 任何东西

(*) 将十进制转换为二进制浮点数比大多数人意识到的要微妙得多。参见 this series of blog posts