Memory leaks F try/catch块中的MailboxProcessor内存泄漏

Memory leaks F try/catch块中的MailboxProcessor内存泄漏,memory-leaks,f#,try-catch,tail-recursion,agents,Memory Leaks,F#,Try Catch,Tail Recursion,Agents,在John Palmer在评论中指出明显错误后更新 以下代码导致OutOfMemoryException: 如果我不使用try/catch块,错误就消失了 增加睡眠时间只会推迟错误 更新2:我想这里的问题是函数不再是尾部递归的,因为递归调用不再是最后一个执行的调用。如果有人有更多的F经验,最好将其卸载,因为我确信这是F代理中常见的内存泄漏情况,因为代码非常简单和通用。我怀疑问题实际上在这里: while true do agent.Post "hello" 您发布的所有hello都必须

在John Palmer在评论中指出明显错误后更新

以下代码导致OutOfMemoryException:

如果我不使用try/catch块,错误就消失了

增加睡眠时间只会推迟错误


更新2:我想这里的问题是函数不再是尾部递归的,因为递归调用不再是最后一个执行的调用。如果有人有更多的F经验,最好将其卸载,因为我确信这是F代理中常见的内存泄漏情况,因为代码非常简单和通用。

我怀疑问题实际上在这里:

while true do
    agent.Post "hello"
您发布的所有hello都必须存储在内存中的某个位置,并且推送的速度将远远快于printf解决方案的输出速度:

这是一个更大问题的一部分:如果递归调用是在try/catch块中进行的,那么函数就不能是尾部递归的,因为如果抛出异常,它必须能够展开堆栈,因此必须保存调用堆栈信息

详情如下:

正确重写的代码分别尝试/捕获和返回:

看到我以前的帖子了吗

随机字符以满足此站点规则*
基本上,在返回后执行的任何操作,如try/with/finally/dispose,都可以防止尾部调用


还有一项工作正在进行,就是让编译器警告缺少尾部递归:

Brilliant。该死,就在我认为我已经找到了我最初问题的原因的时候。看起来这需要更多的调查。我已经更新了问题,以更好地反映我的问题并避免出现错误。如果你总结了你博客文章的内容,而不是简单地在答案中添加链接,这个答案会更好。只有链接的答案的缺点是不太有用,更难扫描答案以找到好的信息,并且容易受到链接腐烂的影响。
while true do
    agent.Post "hello"
let agent = MailboxProcessor<string>.Start(fun agent ->

    let maxLength = 1000

    let rec loop (state: string list) i = async {
        let! msg = agent.Receive()

        let newState = 
            try        
                printfn "received message: %s, iteration: %i, length: %i" msg i state.Length
                let truncatedState = state |> Seq.truncate maxLength |> Seq.toList
                msg::truncatedState
            with
            | ex -> 
                printfn "%A" ex
                state

        return! loop newState (i+1)
    }

    loop [] 0
)