我在Go中使用openCV,并具有以下功能:
func ConvertMatToSlice(c_Mat *CMatrix) []float32 {
c_output := C.Convert(c_Mat.CType)
h := &reflect.SliceHeader{
Data: uintptr(unsafe.Pointer(c_output.val)),
Len: int(c_output.length),
Cap: int(c_output.length),
}
return *(*[]float32)(unsafe.Pointer(h))
}
当我运行go vet ./...
时,它会给我:
opencv_wrapper.go:31:7: unsafeptr: possible misuse of reflect.SliceHeader (govet)
h := &reflect.SliceHeader{
^
有没有其他的方法来获得切片,因为我相信去兽医有它的理由抱怨这一点。
2条答案
按热度按时间ua4mk5z41#
请参见Go Issue #40701。更安全的替代方案如下:
我做了一个test program模拟你的代码行为,而不使用cgo。因此,让我们将其放在一个目录中,并使用
go build -gcflags "-m -m"
进行一些转义分析。我们感兴趣的是确保我们返回的切片(切片头)在堆上分配,它在
Data
字段中指向的指针也是如此。正如我们从逃逸分析中看到的,b
逃逸,切片分配也逃逸:在您的例子中,您必须从C代码中确保指针在堆上分配。
一般来说,从我提到的Go问题的讨论中可以得出的规则是永远不要自己创建SliceHeaders。它们可能会起作用,但它们会导致内存损坏,在代码中造成困难和难以调试的情况。如果您确实需要自己访问切片,可以使用
make
或reflect.MakeSlice
,它们可以保证正常工作,并与GC正确协作,然后对切片头进行必要的更改。mwngjboj2#
在Go 1.21中,refelect.SliceHeader头的使用已经被删除。执行类似操作的替代代码现在如下所示
前面的答案中所说的一切仍然有效。