Pointers 在Go中使用不安全的指针造成恐慌
代码是:Pointers 在Go中使用不安全的指针造成恐慌,pointers,go,slice,unsafe,Pointers,Go,Slice,Unsafe,代码是: package main import ( "fmt" "unsafe" ) type Point struct { x int y int } func main() { buf := make([]byte, 50) fmt.Println(buf) t := (*Point)(unsafe.Pointer(&buf)) t.x = 10 t.y = 100 fmt.Printl
package main
import (
"fmt"
"unsafe"
)
type Point struct {
x int
y int
}
func main() {
buf := make([]byte, 50)
fmt.Println(buf)
t := (*Point)(unsafe.Pointer(&buf))
t.x = 10
t.y = 100
fmt.Println(buf)
}
运行时,会发生运行时死机:
panic: runtime error: invalid memory address or nil pointer dereference
[signal 0xb code=0x1 addr=0xa pc=0x43dd4d]
为什么?因为
buf
是一个片(不是数组),片只是描述符
您很可能希望写入已分配字节的内存空间,因此,不要使用片描述符的地址,而是使用已分配字节的地址,您可以通过获取第一个元素的地址(片描述底层数组的连续部分)获得该地址:
输出(在上尝试):
如您所见,您设置的数据显示在第二个输出中(10 0 0 0
是int
值10
的4个字节,100 0 0 0
是int
值100
的4个字节)
如果使用片描述符的地址,您会看到恐慌,因为描述符包含第一个元素的地址、元素计数和容量等内容。因此,通过使用描述符的地址,您将修改这些内容,并且在尝试再次将其作为片打印时,写入其中的数据很可能位于无效指针中。这通过您以十六进制写入值10
来确认,该值为0xa
,错误消息包含:addr=0xa
另一种选择是使用“实”数组而不是切片,因为数组不是描述符:
buf := [50]byte{}
t := (*Point)(unsafe.Pointer(&buf))
通过这个更改,输出将是相同的。我认为“make([]字节,50)”和“[50]字节{}”以前是相同的。非常感谢。@xiaobaowei
make([]字节,50)
是一个创建切片的程序,[50]字节{}
是一个创建数组类型值的程序。[50]字节
。不要使用包不安全。@Volker在性能相关的应用程序中有很多不安全的用法,尽管它被称为“不安全”,如果你用对了,它绝对没什么问题。我会说“不要用不安全的软件包在内存中随意翻找,期待任何好的东西”。我计算了将指针转换为片而不了解片在内存中如何表示为“随机戳内存”的不安全结果。
[0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0]
[10 0 0 0 100 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0]
buf := [50]byte{}
t := (*Point)(unsafe.Pointer(&buf))