登录
首页 >  Golang >  Go问答

当 CMatrix 转换为切片时,Go-vet 抱怨 unsafeptr

来源:stackoverflow

时间:2024-04-20 08:36:36 105浏览 收藏

今天golang学习网给大家带来了《当 CMatrix 转换为切片时,Go-vet 抱怨 unsafeptr》,其中涉及到的知识点包括等等,无论你是小白还是老手,都适合看一看哦~有好的建议也欢迎大家在评论留言,若是看完有所收获,也希望大家能多多点赞支持呀!一起加油学习~

问题内容

我正在使用 opencv 和 go 并具有此功能:

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{
         ^

有没有其他方法可以得到切片,因为我确信 go-vet 有理由抱怨这一点。


解决方案


请参阅 Go Issue #40701。更安全的替代方案如下:

func convertmattoslice(c_mat *cmatrix) []float32 {
    c_output := c.convert(c_mat.ctype)
    result := make([]float32, c_output.length)
    sh := (*reflect.sliceheader)(unsafe.pointer(&result))
    sh.data = uintptr(unsafe.pointer(c_output.val))
    return result
}

我在不使用 cgo 的情况下制作了一个 test program 来模拟您代码的行为。因此,让我们将其放在一个目录中,并使用 go build -gcflags "-m -m" 进行一些逃逸分析。

我们感兴趣的是确保我们返回的切片(切片头)分配在堆上,并且它指向 data 字段中的指针也是如此。从逃逸分析中我们可以看到,b 逃逸了,切片分配也逃逸了:

./main.go:10:6: b escapes to heap:
./main.go:10:6:   flow: {storage for &output literal} = &b:
./main.go:10:6:     from &b (address-of) at ./main.go:17:38
[...]
./main.go:25:16: make([]float32, c_output.length) escapes to heap:
./main.go:25:16:   flow: {heap} = &{storage for make([]float32, c_output.length)}:
./main.go:25:16:     from make([]float32, c_output.length) (non-constant size) at ./main.go:25:16

就您而言,您必须从 c 代码中确保指针已分配在堆上。

一般来说,从我引用的 go 问题的讨论中可以得出的规则是永远不要自己创建 sliceheaders。它们可能会起作用,但它们可能并且将会导致内存损坏,从而在代码中造成困难且难以调试的情况。如果您确实需要自己访问切片,请使用 make 或使用 reflect.MakeSlice 来执行此操作,它们保证可以正常工作并与 gc 正确配合,然后对切片标头进行必要的更改。

在 go 1.21 中,reflect.sliceheader 标头的使用已被废弃。现在执行类似操作的替代代码如下所示

func ConvertMatToSlice(c_Mat *CMatrix) []float32 {
    c_output := C.Convert(c_Mat.CType)
    sh := unsafe.Slice(c_output.val, c_output.length)
    return *(*[]float32)(unsafe.Pointer(&sh))
}

之前回答中所说的一切仍然有效。

终于介绍完啦!小伙伴们,这篇关于《当 CMatrix 转换为切片时,Go-vet 抱怨 unsafeptr》的介绍应该让你收获多多了吧!欢迎大家收藏或分享给更多需要学习的朋友吧~golang学习网公众号也会发布Golang相关知识,快来关注吧!

声明:本文转载于:stackoverflow 如有侵犯,请联系study_golang@163.com删除
相关阅读
更多>
最新阅读
更多>
课程推荐
更多>