Is this runtime.KeepAlive call really necessary

101 views
Skip to first unread message

Chong Yuan

unread,
Feb 2, 2024, 1:05:58 PM2/2/24
to golang-nuts
Here is the example in our gorocksdb:

// Get returns the data associated with the key from the database.

func (db *DB) Get(opts *ReadOptions, key []byte) (*Slice, error) {

               var (

                              cErr    *C.char

                              cValLen C.size_t

                              cKey    = byteToChar(key)

               )

               cValue := C.rocksdb_get(db.c, opts.c, cKey, C.size_t(len(key)), &cValLen, &cErr)

               runtime.KeepAlive(key)  //<==this is the customization we added.

               if cErr != nil {

                              defer C.rocksdb_free(unsafe.Pointer(cErr))

                              return nil, errors.New(C.GoString(cErr))

               }

               return NewSlice(cValue, cValLen), nil

}

// byteToChar returns *C.char from byte slice.

func byteToChar(b []byte) *C.char {

               var c *C.char

               if len(b) > 0 {

                              c = (*C.char)(unsafe.Pointer(&b[0]))

               }

               return c

}

My question is: if the keepalive(key) is necessary above. Will the "key" be GC-ed when calling into C.rocksdb_get(). Does the compiler know there’s a reference to “key” (using unsafe.pointer) and not collect “key” when running GC?

Ian Lance Taylor

unread,
Feb 2, 2024, 1:11:56 PM2/2/24
to Chong Yuan, golang-nuts
That call to runtime.KeepAlive does not look necessary. Pointers
passed to cgo functions are kept alive for the duration of the call.
The pointer returned by byteToChar will keep the slice's backing array
alive.

Ian
Reply all
Reply to author
Forward
0 new messages