@@ -39,9 +39,9 @@ var useGoAllocation = invariants.RaceEnabled && rand.Uint32()%2 == 0
3939// runtime page allocator and allocate large chunks of memory using mmap or
4040// similar.
4141
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.
4545func New (purpose Purpose , n uintptr ) Buf {
4646 if n == 0 {
4747 return Buf {}
@@ -67,6 +67,8 @@ func New(purpose Purpose, n uintptr) Buf {
6767 // passing uninitialized C memory to Go code if the Go code is going to
6868 // store pointer values in it. Zero out the memory in C before passing it
6969 // to Go.
70+ //
71+ // See https://github.com/golang/go/issues/19928
7072 ptr := C .calloc (C .size_t (n ), 1 )
7173 if ptr == nil {
7274 // NB: throw is like panic, except it guarantees the process will be
@@ -77,6 +79,36 @@ func New(purpose Purpose, n uintptr) Buf {
7779 return Buf {data : ptr , n : n }
7880}
7981
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+
80112// Free frees the specified slice. It has to be exactly the slice that was
81113// returned by New.
82114func Free (purpose Purpose , b Buf ) {
0 commit comments