gpt4 book ai didi

haskell - 为什么这段代码在优化开启或关闭时表现不同?

转载 作者:行者123 更新时间:2023-12-04 03:53:17 27 4
gpt4 key购买 nike

我的 OpenPGP 模块 https://github.com/singpolyma/OpenPGP-Haskell/blob/master/Data/OpenPGP.hs 中的错误有一个简单的测试运行程序:

module Main where

import Data.OpenPGP
import Data.Binary (encode, decode)

packet = EmbeddedSignaturePacket (signaturePacket 2 168 ECDSA SHA256 [] [SignatureCreationTimePacket 1013401916,IssuerPacket "36FE856F4219F1C7"] 48065 [MPI 4,MPI 11,MPI 60,MPI 69,MPI 37,MPI 33,MPI 18,MPI 72,MPI 41,MPI 36,MPI 43,MPI 41,MPI 53,MPI 9,MPI 53,MPI 35,MPI 3,MPI 40,MPI 14,MPI 79,MPI 1,MPI 4,MPI 51,MPI 23,MPI 62,MPI 62,MPI 62,MPI 7,MPI 68,MPI 51,MPI 13,MPI 49,MPI 8,MPI 64,MPI 32,MPI 50,MPI 59,MPI 17,MPI 43,MPI 12,MPI 67,MPI 5,MPI 67,MPI 5,MPI 25,MPI 63,MPI 0,MPI 53,MPI 2,MPI 36,MPI 83,MPI 39,MPI 54,MPI 65,MPI 54,MPI 35,MPI 62,MPI 63,MPI 26,MPI 4,MPI 82,MPI 57,MPI 85,MPI 71,MPI 43,MPI 77])

main = print $ decode (encode packet) == packet

如果你编译这个(在 ghc 7.4.1 上):
ghc -O0 -fforce-recomp --make t.hs

它按预期工作(即,它打印 True ),但如果你像这样编译:
ghc -O1 -fforce-recomp --make t.hs

或这个:
ghc -O2 -fforce-recomp --make t.hs

它将打印 False .

我没有使用任何扩展(除了对 CPP 的微不足道的使用)或低级或不安全的调用,并且行为应该来自我的库而不是依赖项,因为只有我的代码在这里重新编译。

最佳答案

这是您的代码中的错误。考虑

MPI 63,MPI 0,MPI 53
^^^^^


instance BINARY_CLASS MPI where
put (MPI i) = do
put (((fromIntegral . B.length $ bytes) - 1) * 8
+ floor (logBase (2::Double) $ fromIntegral (bytes `B.index` 0))
^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+ 1 :: Word16)
putSomeByteString bytes
where
bytes = if B.null bytes' then B.singleton 0 else bytes'
bytes' = B.reverse $ B.unfoldr (\x ->
if x == 0 then Nothing else
Just (fromIntegral x, x `shiftR` 8)
) (assertProp (>=0) i)

现在,如果我们编码 MPI 0 , bytes'为空,因此 bytes = B.singleton 0因此 bytes `B.index` 0为 0。

但是 logBase 2 0-Infinity , 和 floor仅对有限值(在目标类型的范围内)定义明确。

在没有优化的情况下编译时, floor通过 decodeFloat 使用位模式.然后 floor (logBase 2 0)对于所有标准的固定宽度整数类型,产生 0。

通过优化,重写规则处于事件状态, floor使用 primop double2Int# ,它在 x86 上返回硬件所做的任何事情。 x86-64,即 minBound :: Int ,据我所知,无论位模式如何。相关代码是
floorDoubleInt :: Double -> Int
floorDoubleInt (D# x) =
case double2Int# x of
n | x <## int2Double# n -> I# (n -# 1#)
| otherwise -> I# n

当然, -Infinity < int2Double minBound ,所以值变为 minBound - 1 ,通常是 maxBound .

当然这会导致错误的结果,因为现在“长度”是 put对于 MPI 0变为 0,“长度”字段后面的 0 字节被解释为下一个 MPI 的“长度”的一部分.

关于haskell - 为什么这段代码在优化开启或关闭时表现不同?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/12361085/

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