【发布时间】:2015-08-19 19:19:45
【问题描述】:
我有以下problem 1-4 of the Matasano Cryptopals Challenge 的实现,用于在文件中找到一行,该行是与单个字节异或的文本字符串。它适用于大文件,但显示“堆栈空间溢出:当前大小 8388608 字节”。对于提供的文件。
import System.IO
import System.Environment
import Control.Monad
import Data.Bits
import Data.Word
import Data.Maybe
import Data.List hiding (maximumBy)
import Data.Char
import Data.Ord
import Data.Foldable hiding (sum)
hexChars = "0123456789ABCDEF"
hexToBytes :: String -> Maybe [Word8]
{- Converts a hex string into a byte array -}
hexToBytes hexes = hexToBytes' (map toUpper hexes)
hexToBytes' (char1 : char2 : xs) = do
tail <- hexToBytes' xs
byte1 <- char1 `elemIndex` hexChars
byte2 <- char2 `elemIndex` hexChars
return ((fromIntegral(byte1*16 + byte2) :: Word8) : tail)
hexToBytes' [_] = Nothing
hexToBytes' [] = Just []
maxBy :: Ord b => Foldable f => (a -> b) -> f a -> a
maxBy = maximumBy . comparing
bytesToString :: Integral i => Monad m => m i -> m Char
bytesToString = liftM (chr . fromIntegral)
isLowercase x = (x >= 'a') && (x <= 'z')
asciiCheck :: Word8 -> Int
asciiCheck x = if (isLowercase . chr . fromIntegral) x then 1 else 0
score = (sum . map asciiCheck)
readLines :: Handle -> IO [String]
readLines handle = do
eof <- hIsEOF handle
if eof then
return []
else liftM2 (:) (hGetLine handle) (readLines handle)
decode key = map (xor key)
keys = [minBound ..] :: [Word8]
massDecode inputs =
maxBy score (liftM2 decode keys inputs)
main = do
hSetEncoding stdout latin1
args <- getArgs
handle <- case args of
[] -> return stdin
(x:xs) -> openFile x ReadMode
lines <- readLines handle
putStrLn $ bytesToString $ massDecode $ catMaybes $ map hexToBytes lines
该程序通过遍历一个列表来工作,该列表包含与每个可能的键异或的每个输入行。我怀疑这个大列表以某种方式导致了溢出,但我认为这不会导致内存问题,因为列表会延迟生成。我认为我对何时评估 thunk 没有足够的了解,无法直观地了解这是如何导致堆栈溢出的。
所以我的问题是:为什么生成或遍历这个列表会导致堆栈溢出?
【问题讨论】:
-
是的,你的代码会有所帮助 - 在那之前你可以看看this Wiki article dealing with the different folds and their properties
-
foldl'可能会缓解任何空间问题... -
另外,请确保您正在编译优化 (
-O2)。 -
@recursion.ninja:我使用 maximumBy 进行折叠。
-
好吧,因为有人删除了我的答案(诚然没有充实,但我在工作,没有时间完成它),你正在运行的问题有一个很好的解释进入here
标签: performance haskell stack-overflow lazy-evaluation