亚洲在线久爱草,狠狠天天香蕉网,天天搞日日干久草,伊人亚洲日本欧美

為了賬號安全,請及時綁定郵箱和手機立即綁定
已解決430363個問題,去搜搜看,總會有你想問的

在 Go 中使用 unsafe.Pointer 的恐慌

在 Go 中使用 unsafe.Pointer 的恐慌

Go
慕村225694 2021-11-01 10:51:11
代碼是:package mainimport (    "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]為什么?
查看完整描述

1 回答

?
函數式編程

TA貢獻1807條經驗 獲得超9個贊

因為buf是切片(不是數組),切片只是描述符。


您很可能想寫入分配字節的內存空間,因此不要使用切片描述符的地址,而是使用分配字節的地址,您可以通過獲取第一個元素的地址來獲得(切片描述底層數組的連續部分):


t := (*Point)(unsafe.Pointer(&buf[0]))

輸出(在Go Playground上試試):


[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]

正如你可以看到,可以設置數據出現在第二輸出(10 0 0 0是4個字節的int值10,100 0 0 0是4個字節的int值100)。


如果您使用切片描述符的地址,您會看到恐慌,因為描述符包含諸如第一個元素的地址、元素計數和容量之類的內容。因此,通過使用描述符的地址,您將修改這些地址,并且在嘗試將其作為切片再次打印時,您寫入的數據很可能位于無效指針中。您可以通過寫入十六進制值來確認10這一點0xa,并且錯誤消息包含:addr=0xa


另一種選擇是使用“真實”數組而不是切片,因為數組不是描述符:


buf := [50]byte{}

t := (*Point)(unsafe.Pointer(&buf))

有了這個改變,輸出將是相同的。


查看完整回答
反對 回復 2021-11-01
  • 1 回答
  • 0 關注
  • 199 瀏覽
慕課專欄
更多

添加回答

舉報

0/150
提交
取消
微信客服

購課補貼
聯系客服咨詢優惠詳情

幫助反饋 APP下載

慕課網APP
您的移動學習伙伴

公眾號

掃描二維碼
關注慕課網微信公眾號