终结者(x,f)
当没有时,注册要调用的函数f(x) 程序可访问的x引用。 x的类型必须是可变的 struct,否则此函数的行为是不可预测的。
然而,我似乎在观察他们在我的类型的第一次引用丢失其最后一个引用时触发。
考虑:
using Base.Test
mutable struct Foo
val
end
@testset "how do Finalisers work" begin let
fin_calls = []
a = Foo(1)
b = a
finalizer(a, _ -> push!(fin_calls, "a"))
finalizer(b, _ -> push!(fin_calls, "b"))
@test fin_calls == []
a = 7
gc()
@test fin_calls == [] # Fails: Evaluated: Any["a", "b"] == Any[]
#shouldn't trigger finaliser as still has 1 ref, or so I thought
b=8
gc()
@test Set(fin_calls) == Set(["a", "b"]) #both finalizers should trigger
end end
我的Foo(1)
有2个引用,分别是a
和b
a
更改为其他内容时,没有任何反应b
也被更改为其他内容时,两个注册finalizers
都会触发。导致" a"和" b"两者都要添加到fin_calls
数组中。我原以为:
a
更改为其他内容时,两个注册finalizers
都会触发。导致" a"和" b"两者都要添加到fin_calls
数组中。b
也被更改,则不会发生任何其他情况。了解正在发生的事情的正确方法是什么? 这是在朱莉娅6.0
我重现这一点的能力似乎各不相同。
答案 0 :(得分:2)
如果你不使用变量, 垃圾收集器可以在上次使用后随时收集变量。
如果您根本不使用变量,那么优化器可以根本不在实际代码中生成它。
我相信这就是发生的事情。 如果我添加一些变量用途,行为就像预期的那样。
using Base.Test
"This function makes use of `xs` in a way no optimizer can possibly remove"
function use(xs...)
mktemp() do fn, fh
print(fh, xs)
end
end
mutable struct Foo
val
end
function foo()
@testset "how do Finalisers work" begin let
fin_calls = []
a = Foo(1)
b = a
finalizer(a, _ -> push!(fin_calls, "a"))
finalizer(b, _ -> push!(fin_calls, "b"))
use(a,b)
@test fin_calls == []
a = 7
gc()
use(b)
@test fin_calls == [] # Fails: Evaluated: Any["a", "b"] == Any[]
#shouldn't trigger finaliser as still has 1 ref, or so I thought
b=8
gc()
@test Set(fin_calls) == Set(["a", "b"]) #both finalizers should trigger
end end
这段代码,对我来说是最终的测试然后失败,因为那时fin_calls
从未被调用过。因为垃圾收集器可以选择不运行。
结束