Invalid GC results in F# tests
Why some objects seem not to be collected
When running tests which check if something is GC’d, it might fail.
The test
Consider the following test:
[<TestMethod>]
member _.TestGC() =
let mutable obj = new Object()
let weak = new WeakReference(obj);
GC.Collect()
Assert.IsTrue(obj <> null)
Assert.IsTrue(weak.IsAlive)
obj <- null
GC.Collect()
Assert.IsTrue((obj = null))
Assert.IsTrue(not weak.IsAlive)
This will fail in DEBUG
.
Sub-expression elaboration
This happens because of elaboration to new locals for every subexpression. For example,
let list1 = [1; 2; 3]
let list2 = [1; 2; 3]
assert (list1 = list2)
This elaborates every sub-expression to:
let list1 = [1; 2; 3]
let list2 = [1; 2; 3]
let list1' = list1
let list2' = list2
let is_eq = list1'.Equals(list2')
assert (is_eq)
Rewriting our first example:
let obj' = obj
let isNull = obj' <> null
While this usually isn’t a problem, obj'
will end up holding a reference to the original object, so it won’t be collected until it goes out of scope - which is only when the method exits.
The rewriting won’t happen for RELEASE
mode, so the test should pass. But any effects related to the lifetime of objects in memory would exist in DEBUG
.
Last modified on 2020-03-30
Comments Disabled.