Asti's Notes
FP, Rx, EDA
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.