以下定义导致内存泄漏:
def enumIterator1[E, F[_]: Monad](x: => Iterator[E]) : EnumeratorT[E, F] =
new EnumeratorT[E, F] {
def apply[A] = (s: StepT[E, F, A]) => {
def go(xs: Iterator[E]): IterateeT[E, F, A] =
if(xs.isEmpty) s.pointI
else {
val next = xs.next
s mapCont { k =>
k(Iteratee.elInput(next)) >>== enumIterator1[E, F](xs).apply[A]
}
}
go(x)
}
}
通过以下测试可以观察到泄漏:
(Iteratee.fold[Array[Byte], IO, Long](0L)(_+_.length)
&= enumIterator1(
Iterator.continually(
Array.fill(1 << 16)(0.toByte)).take(1 << 16))
).run.unsafePerformIO
但是,一个小的更改(即移动xs.next
调用)会阻止泄漏:
def enumIterator1[E, F[_]: Monad](x: => Iterator[E]) : EnumeratorT[E, F] =
new EnumeratorT[E, F] {
def apply[A] = (s: StepT[E, F, A]) => {
def go(xs: Iterator[E]): IterateeT[E, F, A] =
if(xs.isEmpty) s.pointI
else {
// val next = xs.next (moved down)
s mapCont { k =>
val next = xs.next
k(Iteratee.elInput(next)) >>== enumIterator1[E, F](xs).apply[A]
}
}
go(x)
}
}
为什么?
我有一个模糊的概念,即解释与闭包的参考模式有关,但我无法提出这种行为的具体原因。我正在尝试追踪不同的内存泄漏,并且我怀疑(希望?)了解此泄漏可能有助于确定导致该泄漏的原因。