如果我使用crash
和50000000(五千万)的任何值调用increment
进行旋转,它会逐渐增加并保持内存大小增长,直到每个内存都被阻塞然后崩溃。
crash :: Int -> Int -> Int
crash increment spins = snd $ foldl' spin' (0,0) [1..spins]
where spin' = spin increment
spin increment (index,element1) spinNumber = (next,nextElementOne)
where
next
| indexNIncrement >= spinNumber = 1 + (indexNIncrement `rem` spinNumber)
| otherwise = 1 + indexNIncrement
indexNIncrement = index + increment
nextElementOne
| next==1 = spinNumber
| otherwise = element1
我不知道内存是如何泄露的。是否每次调用spin
都会替换累加器值?它不会被释放吗?
答案 0 :(得分:3)
基本上,在每个步骤foldl'
将在每一步评估函数spin'
的结果,将其带到WHNF(弱头正常形式)。具体来说,这意味着将在第一个构造函数之前评估结果。
然而,spin'
的结果是(next,nextElementOne)
,它已经在WHNF中,因为它以一对构造函数开头。我们想要的是在这里强制评估对组件。一个基本的解决方案是返回
spin ... = next `seq` (nextElementOne `seq` (next, nextElementOne))
以便在返回对之前评估组件。
更现代的方法可能是利用BangPatterns
。