go vet: misuse of unsafe.Pointer
Closed this issue · 2 comments
mdimec4 commented
-
My system
Ubuntu 14.04.3 LTS \n \l Linux ... 3.13.0-76-generic #120-Ubuntu SMP Mon Jan 18 15:59:10 UTC 2016 x86_64 x86_64 x86_64 GNU/Linux go version go1.7 linux/amd64
-
The problem is with Go runtime
go vet github.com/mattn/go-pointer src/github.com/mattn/go-pointer/pointer.go:20: possible misuse of unsafe.Pointer exit status 1
If I
go vet
the lib, I get the described error. After some research, I have found that one should not cast integers to pointer, with the result where we end up with invalid dangling pointer.See https://golang.org/doc/go1.3 section "Changes to the garbage collector"
From described I expect, that this code can be problematic.
-
Possible solution would, be to make index pointer actually valid:
This seems to work:
// based on https://github.com/mattn/go-pointer
package main
//#include <stdlib.h>
import "C"
import (
"sync"
"unsafe"
)
var (
cgoPointerHackLock sync.Mutex
cgoPointerHackMap map[unsafe.Pointer]interface{} = map[unsafe.Pointer]interface{}{}
)
// Since Go 1.6, cgo argument can't be passed Go pointer. (see https://golang.org/doc/go1.6#cgo )
// Trick here is to store Go data links inside map, which is indexed by valid C pointers.
// C memory allocated for indexing is not really used, but should satisfy request,
// that unsafe.Pointer should always point to valid data. (see (Changes to GC section): https://golang.org/doc/go1.3 )
func cgoPointerHackSave(v interface{}) unsafe.Pointer {
if v == nil {
return nil
}
var ptr unsafe.Pointer
// find next available pointer
cgoPointerHackLock.Lock()
// Generate real fake C pointer.
// This pointer will not store any data, but will bi used for indexing purposes.
// Since Go doest allow to cast dangling pointer to unsafe.Pointer, we do rally allocate one byte.
// Why we need indexin, because Go doest allow C code to store pointers to Go data.
ptr = C.malloc(C.size_t(1))
if ptr == nil {
cgoPointerHackLock.Unlock()
panic("can't allocate 'cgo-pointer hack index pointer': ptr == nil")
//return
}
cgoPointerHackMap[ptr] = v
cgoPointerHackLock.Unlock()
return ptr
}
func cgoPointerHackGet(ptr unsafe.Pointer, unref bool) interface{} {
if ptr == nil {
return nil
}
cgoPointerHackLock.Lock()
if v, ok := cgoPointerHackMap[ptr]; ok {
if unref {
delete(cgoPointerHackMap, ptr)
C.free(ptr)
}
cgoPointerHackLock.Unlock()
return v
}
cgoPointerHackLock.Unlock()
return nil
}
func cgoPointerHackUnref(ptr unsafe.Pointer) {
if ptr == nil {
return
}
cgoPointerHackLock.Lock()
delete(cgoPointerHackMap, ptr)
C.free(ptr)
cgoPointerHackLock.Unlock()
}
mdimec4 commented
No problem.
Your trick proved very very useful with GTK and webkit2gtk callbacks and signals :D
Thank you for that.