Line data Source code
1 : // Copyright 2020 The LevelDB-Go and Pebble Authors. All rights reserved. Use 2 : // of this source code is governed by a BSD-style license that can be found in 3 : // the LICENSE file. 4 : 5 : //go:build (invariants && !race) || (tracing && !race) 6 : // +build invariants,!race tracing,!race 7 : 8 : package cache 9 : 10 : import ( 11 : "fmt" 12 : "os" 13 : 14 : "github.com/cockroachdb/pebble/internal/invariants" 15 : "github.com/cockroachdb/pebble/internal/manual" 16 : ) 17 : 18 : // newValue creates a Value with a manually managed buffer of size n. 19 : // 20 : // This definition of newValue is used when either the "invariants" or 21 : // "tracing" build tags are specified. It hooks up a finalizer to the returned 22 : // Value that checks for memory leaks when the GC determines the Value is no 23 : // longer reachable. 24 2 : func newValue(n int) *Value { 25 2 : if n == 0 { 26 0 : return nil 27 0 : } 28 2 : b := manual.New(n) 29 2 : v := &Value{buf: b} 30 2 : v.ref.init(1) 31 2 : // Note: this is a no-op if invariants and tracing are disabled or race is 32 2 : // enabled. 33 2 : invariants.SetFinalizer(v, func(obj interface{}) { 34 2 : v := obj.(*Value) 35 2 : if v.buf != nil { 36 0 : fmt.Fprintf(os.Stderr, "%p: cache value was not freed: refs=%d\n%s", 37 0 : v, v.refs(), v.ref.traces()) 38 0 : os.Exit(1) 39 0 : } 40 : }) 41 2 : return v 42 : } 43 : 44 2 : func (v *Value) free() { 45 2 : // When "invariants" are enabled set the value contents to 0xff in order to 46 2 : // cache use-after-free bugs. 47 2 : for i := range v.buf { 48 2 : v.buf[i] = 0xff 49 2 : } 50 2 : manual.Free(v.buf) 51 2 : // Setting Value.buf to nil is needed for correctness of the leak checking 52 2 : // that is performed when the "invariants" or "tracing" build tags are 53 2 : // enabled. 54 2 : v.buf = nil 55 : }