将指针参数传递给 unsafe.Pointer

问题描述 投票:0回答:0

使用有什么问题

方法一:

func Encode(v *float32) []byte {
    return unsafe.Slice((*byte)(unsafe.Pointer(v)), 4)
}

结束

方法 2

func Encode(v float32) []byte {
    return unsafe.Slice((*byte)(unsafe.Pointer(&v)), 4)
}

两者都在 Little Endian System 上运行。唯一的区别是Approach 1接受一个指针作为参数,而Approach 2接受一个值作为参数。

我正在调试一个与

相关的问题

fatal error: found bad pointer in Go heap (incorrect use of unsafe or cgo?)

found pointer to free object | bad use of unsafe.Pointer? 

我终于发现根本原因可能是由于方法 1 的使用。有人可以让我知道方法 1 可能有什么问题吗?一般推荐使用Approach 2吗?

请注意

float32
是功能之一。还有其他编码功能也接受
byte arrays
int8
等。

type Uuid [16]byte

func EncodeUuid(v *Uuid) []byte {
    return unsafe.Slice((*byte)(unsafe.Pointer(v)), UuidSize)
}

这里的 SO 答案 提到可以在调用

Encode()
函数之前对原始变量进行 GC。尝试访问已释放指针指向的内存可能会导致“找到指向自由对象的指针”错误。

下面是执行过程中发现的错误日志

错误日志 1

runtime: marked free object in span 0x7fef20c4c8a8, elemsize=24 freeindex=0 (bad use of unsafe.Pointer? try -d=checkptr)
0xc14a028000 free  unmarked
0xc14a028018 free  unmarked
0xc14a028030 free  unmarked
0xc14a028048 free  unmarked
0xc14a028060 free  unmarked
0xc14a028078 free  marked   zombie
0x000000c14a028078:  0x000000c0003f2800  0x0000000000000800 
0x000000c14a028088:  0x0000000000000800 
0xc14a028090 free  unmarked
0xc14a029fc8 free  unmarked
0xc14a029fe0 free  unmarked
fatal error: found pointer to free object

goroutine 1482447 [running]:
runtime.throw({0x29b9a01?, 0xc14a028090?})
    /usr/lib/golang/src/runtime/panic.go:1047 +0x5d fp=0xc2555a2ae0 sp=0xc2555a2ab0 pc=0x44775d
runtime.(*mspan).reportZombies(0x7fef20c4c8a8)
    /usr/lib/golang/src/runtime/mgcsweep.go:788 +0x2e5 fp=0xc2555a2b60 sp=0xc2555a2ae0 pc=0x435dc5

错误日志 2

runtime: pointer 0xc079e0001d to unallocated span span.base()=0xc079dfe000 span.limit=0xc079e2e010 span.state=0
runtime: found in object at *(0xc032b5c180+0x28)
object=0xc032b5c180 s.base()=0xc032b5c000 s.limit=0xc032b5e000 s.spanclass=20 s.elemsize=128 s.state=mSpanInUse
 *(object+0) = 0x0
 *(object+8) = 0x400000016
 *(object+16) = 0xffffffff00000020
 *(object+24) = 0x3a665e0
 *(object+32) = 0xc0dde3d110
 *(object+40) = 0xc079e0001d <==
 *(object+48) = 0x8000
 *(object+56) = 0x8008
 *(object+64) = 0x0
 *(object+72) = 0x0
 *(object+80) = 0x0
 *(object+88) = 0x2
 *(object+96) = 0x2000
 *(object+104) = 0x6174620
 *(object+112) = 0x101
 *(object+120) = 0x0
fatal error: found bad pointer in Go heap (incorrect use of unsafe or cgo?)

错误日志 3

fatal error: unexpected signal during runtime execution
[signal SIGSEGV: segmentation violation code=0x2 addr=0x450608 pc=0x468c46]

goroutine 1202 [running]:
runtime.throw({0x3f96b81?, 0x0?})
    /usr/local/go/src/runtime/panic.go:1047 +0x5d fp=0xc006433cd0 sp=0xc006433ca0 pc=0x454c7d
runtime.sigpanic()
    /usr/local/go/src/runtime/signal_unix.go:819 +0x369 fp=0xc006433d20 sp=0xc006433cd0 pc=0x46ce09
runtime.(*waitq).enqueue(...)
    /usr/local/go/src/runtime/chan.go:766
runtime.selectgo(0xc006433fb0, 0xc006433ed8, 0x2710?, 0x0, 0x0?, 0x1)
    /usr/local/go/src/runtime/select.go:317 +0x7c6 fp=0xc006433e80 sp=0xc006433d20 pc=0x468c46

任何建议都会很有帮助!

PS: 当 GC 启动时,这个问题很少发生。所以为了有积极的 GC 来测试场景,我目前正在使用

GODEBUG=invalidptr=1,cgocheck=1,madvdontneed=1 GOGC=2 GOMEMLIMIT=10MiB ./my-executable
go unsafe unsafe-pointers
© www.soinside.com 2019 - 2024. All rights reserved.