Do not use try..finally in recursive functions

Recently I stumbled upon a post in Moirae Software blog. It was about hunting a memory leak in a F# application. What was interesting about the leak that it was caused by non-tail recursive call, however the call seemed to be tail at first glance. It turned out that tail calls is full of rather subtle pitfalls. For further information on the topic I recommend this F# team blog post. As a real engineer, I must check everything myself :) This is the results:
In short, the F# team folks are absolutely right - recursive calls from try...with/try...finally block are not tail. In case of non-async (plane) functions it follows to quick stack overflow exception. In case of async functions things gets a bit more interesting due to continuations created by Async expression builder. Although the continuations have 'fixed' the stack overflow problem (effectively have hidden it), the result is even more dangerous - a memory leak. Conclusion is simple:

  • Never, ever do recursive calls from try...with/try...finally blocks!
  • Never, ever use either 'use' nor 'use!' in recursive functions!


Popular posts from this blog

Akka.NET Streams vs Hopac vs AsyncSeq

Regular expressions: Rust vs F# vs Scala

Computing cryptography hashes: Rust, F#, D and Scala