diff options
Diffstat (limited to 'test/fixedbugs/issue27518b.go')
-rw-r--r-- | test/fixedbugs/issue27518b.go | 72 |
1 files changed, 72 insertions, 0 deletions
diff --git a/test/fixedbugs/issue27518b.go b/test/fixedbugs/issue27518b.go new file mode 100644 index 0000000..ea72a30 --- /dev/null +++ b/test/fixedbugs/issue27518b.go @@ -0,0 +1,72 @@ +// run + +// Copyright 2018 The Go Authors. All rights reserved. +// Use of this source code is governed by a BSD-style +// license that can be found in the LICENSE file. + +package main + +import "runtime" + +var finalized bool +var err string + +type HeapObj [8]int64 + +const filler int64 = 0x123456789abcdef0 + +func (h *HeapObj) init() { + for i := 0; i < len(*h); i++ { + h[i] = filler + } +} +func (h *HeapObj) check() { + for i := 0; i < len(*h); i++ { + if h[i] != filler { + err = "filler overwritten" + } + } +} + +type StackObj struct { + h *HeapObj +} + +func gc(shouldFinalize bool) { + runtime.GC() + runtime.GC() + runtime.GC() + if shouldFinalize != finalized { + err = "heap object finalized at the wrong time" + } +} + +func main() { + var s StackObj + s.h = new(HeapObj) + s.h.init() + runtime.SetFinalizer(s.h, func(h *HeapObj) { + finalized = true + }) + gc(false) + h := g(&s) + gc(false) + h.check() + gc(true) // finalize here, after return value's last use. (Go1.11 never runs the finalizer.) + if err != "" { + panic(err) + } +} + +func g(p *StackObj) (v *HeapObj) { + gc(false) + v = p.h // last use of the stack object. the only reference to the heap object is in the return slot. + gc(false) + defer func() { + gc(false) + recover() + gc(false) + }() + *(*int)(nil) = 0 + return +} |