Source file test/fixedbugs/issue27518b.go

     1  // run
     2  
     3  // Copyright 2018 The Go Authors. All rights reserved.
     4  // Use of this source code is governed by a BSD-style
     5  // license that can be found in the LICENSE file.
     6  
     7  package main
     8  
     9  import "runtime"
    10  
    11  var finalized bool
    12  var err string
    13  
    14  type HeapObj [8]int64
    15  
    16  const filler int64 = 0x123456789abcdef0
    17  
    18  func (h *HeapObj) init() {
    19  	for i := 0; i < len(*h); i++ {
    20  		h[i] = filler
    21  	}
    22  }
    23  func (h *HeapObj) check() {
    24  	for i := 0; i < len(*h); i++ {
    25  		if h[i] != filler {
    26  			err = "filler overwritten"
    27  		}
    28  	}
    29  }
    30  
    31  type StackObj struct {
    32  	h *HeapObj
    33  }
    34  
    35  func gc(shouldFinalize bool) {
    36  	runtime.GC()
    37  	runtime.GC()
    38  	runtime.GC()
    39  	if shouldFinalize != finalized {
    40  		err = "heap object finalized at the wrong time"
    41  	}
    42  }
    43  
    44  func main() {
    45  	var s StackObj
    46  	s.h = new(HeapObj)
    47  	s.h.init()
    48  	runtime.SetFinalizer(s.h, func(h *HeapObj) {
    49  		finalized = true
    50  	})
    51  	gc(false)
    52  	h := g(&s)
    53  	gc(false)
    54  	h.check()
    55  	gc(true) // finalize here, after return value's last use. (Go1.11 never runs the finalizer.)
    56  	if err != "" {
    57  		panic(err)
    58  	}
    59  }
    60  
    61  func g(p *StackObj) (v *HeapObj) {
    62  	gc(false)
    63  	v = p.h // last use of the stack object. the only reference to the heap object is in the return slot.
    64  	gc(false)
    65  	defer func() {
    66  		gc(false)
    67  		recover()
    68  		gc(false)
    69  	}()
    70  	*(*int)(nil) = 0
    71  	return
    72  }
    73  

View as plain text