@@ -39,9 +39,9 @@ var useGoAllocation = invariants.RaceEnabled && rand.Uint32()%2 == 0
39
39
// runtime page allocator and allocate large chunks of memory using mmap or
40
40
// similar.
41
41
42
- // New allocates a slice of size n. The returned slice is from manually
43
- // managed memory and MUST be released by calling Free. Failure to do so will
44
- // result in a memory leak.
42
+ // New allocates a slice of size n. The returned slice is from manually managed
43
+ // memory and MUST be released by calling Free. Failure to do so will result in
44
+ // a memory leak.
45
45
func New (purpose Purpose , n uintptr ) Buf {
46
46
if n == 0 {
47
47
return Buf {}
@@ -67,6 +67,8 @@ func New(purpose Purpose, n uintptr) Buf {
67
67
// passing uninitialized C memory to Go code if the Go code is going to
68
68
// store pointer values in it. Zero out the memory in C before passing it
69
69
// to Go.
70
+ //
71
+ // See https://github.com/golang/go/issues/19928
70
72
ptr := C .calloc (C .size_t (n ), 1 )
71
73
if ptr == nil {
72
74
// NB: throw is like panic, except it guarantees the process will be
@@ -77,6 +79,36 @@ func New(purpose Purpose, n uintptr) Buf {
77
79
return Buf {data : ptr , n : n }
78
80
}
79
81
82
+ // NewUninitialized allocates a slice of size n without zeroing it out. The
83
+ // returned slice is from manually managed memory and MUST be released by
84
+ // calling Free. Failure to do so will result in a memory leak (see
85
+ // https://github.com/golang/go/issues/19928).
86
+ //
87
+ // If the caller does an unsafe cast from the slice to any type containing
88
+ // pointers, the relevant part of the slice *must* be zeroed out.
89
+ func NewUninitialized (purpose Purpose , n uintptr ) Buf {
90
+ if n == 0 {
91
+ return Buf {}
92
+ }
93
+ recordAlloc (purpose , n )
94
+
95
+ // In race-enabled builds, we sometimes make allocations using Go to allow
96
+ // the race detector to observe concurrent memory access to memory allocated
97
+ // by this package. See the definition of useGoAllocation for more details.
98
+ if invariants .RaceEnabled && useGoAllocation {
99
+ b := make ([]byte , n )
100
+ return Buf {data : unsafe .Pointer (& b [0 ]), n : n }
101
+ }
102
+ ptr := C .malloc (C .size_t (n ))
103
+ if ptr == nil {
104
+ // NB: throw is like panic, except it guarantees the process will be
105
+ // terminated. The call below is exactly what the Go runtime invokes when
106
+ // it cannot allocate memory.
107
+ throw ("out of memory" )
108
+ }
109
+ return Buf {data : ptr , n : n }
110
+ }
111
+
80
112
// Free frees the specified slice. It has to be exactly the slice that was
81
113
// returned by New.
82
114
func Free (purpose Purpose , b Buf ) {
0 commit comments