Rumah  >  Artikel  >  pembangunan bahagian belakang  >  Bincangkan punca dan penyelesaian kegagalan penunjuk di Golang

Bincangkan punca dan penyelesaian kegagalan penunjuk di Golang

PHPz
PHPzasal
2023-04-27 09:11:05933semak imbas

Golang ialah bahasa yang menekankan keselamatan Salah satu cirinya ialah ia mengehadkan operasi penunjuk, dengan itu menghalang banyak kelemahan keselamatan memori. Walau bagaimanapun, walaupun di Golang, masalah penunjuk tidak sah masih wujud. Artikel ini akan meneroka punca dan penyelesaian kegagalan penunjuk di Golang.

1. Sebab kegagalan penunjuk

Di Golang, ruang memori yang ditunjuk oleh penunjuk mungkin dituntut semula oleh pemungut sampah, menyebabkan penunjuk menjadi tidak sah. Keadaan ini biasanya berlaku dalam situasi berikut:

  1. Selepas penuding dihantar ke fungsi yang dipanggil, ruang memori yang ditunjuk oleh penuding dilepaskan selepas fungsi tamat.

Contohnya, kod berikut:

func foo() *int {
   x := 10
   return &x
}

func main() {
   p := foo()
   fmt.Println(*p)
}

Dalam fungsi foo, pembolehubah x ialah pembolehubah tempatan yang dikeluarkan selepas fungsi tamat. Apabila fungsi kembali, ia mengembalikan alamat x. Dalam fungsi utama, p menunjuk ke alamat yang dikembalikan oleh fungsi foo. Apabila mencetak *p, 10 akan dikeluarkan. Walau bagaimanapun, jika kita cuba untuk terus mengakses ruang memori yang ditunjuk oleh p selepas fungsi foo tamat, kita akan mendapati bahawa penunjuk itu tidak sah.

func main() {
   p := foo()
   fmt.Println(*p)
   fmt.Println(*p) // 这里会触发panic
}
  1. Objek yang ditunjuk oleh penuding dipadamkan atau dialihkan

Jika kita menyimpan penunjuk ke elemen dalam kepingan, apabila kita menambah atau memadam elemen, Penunjuk kepada elemen tidak sah.

Sebagai contoh, kod berikut:

func main() {
   a := []int{1, 2, 3, 4, 5, 6}
   p := &a[2]
   a = append(a, 7)
   fmt.Println(*p) // 这里会发现指针失效了
}

Di sini, kami mentakrifkan kepingan a dan menggunakan &p untuk mendapatkan alamat a[2], kemudian menambah elemen 7. Dalam ungkapan *p berikutnya, kami cuba menggunakan penuding p untuk mengakses a[2], tetapi kerana elemen dilampirkan, a[2] bukan lagi elemen sebelumnya, jadi p menunjuk ke alamat yang tidak sah.

2. Penyelesaian kepada kegagalan penunjuk

  1. Elakkan daripada mengembalikan alamat pembolehubah setempat

Seperti yang dinyatakan di atas, tentukan pembolehubah tempatan dalam fungsi dan ambil Mengembalikan alamatnya akan menyebabkan penuding menjadi tidak sah. Penyelesaiannya adalah dengan menggunakan kata kunci baharu apabila mentakrifkan pembolehubah di dalam fungsi, yang memperuntukkan memori dan mengembalikan penunjuk ke memori itu.

Contohnya, kod berikut:

func foo() *int {
   p := new(int)
   *p = 10
   return p
}

func main() {
   p := foo()
   fmt.Println(*p)
}

Di sini, kami menggunakan fungsi new() untuk memperuntukkan blok memori dan menetapkan nilai yang ditunjukkannya kepada 10. Selepas fungsi tamat, penunjuk ke memori ini dikembalikan. Dengan cara ini, walaupun fungsi tamat, memori tidak akan dikeluarkan dan penunjuk tidak akan menjadi tidak sah.

  1. Gunakan penyegerakan.Mutex

Dalam persekitaran berbilang benang, kami boleh menggunakan penyegerakan.Mutex untuk melindungi penunjuk. Mutex boleh memastikan bahawa hanya satu goroutine boleh mengakses penuding yang dilindungi pada satu masa, dan kemudian melepaskan kunci selepas akses selesai.

Sebagai contoh, kod berikut:

type SafeCounter struct {
   mu sync.Mutex
   count int
}

func (c *SafeCounter) Increment() {
   c.mu.Lock()
   defer c.mu.Unlock()
   c.count++
}

func (c *SafeCounter) Value() int {
   c.mu.Lock()
   defer c.mu.Unlock()
   return c.count
}

Di sini, kami mentakrifkan jenis SafeCounter, yang mengandungi pembolehubah kiraan dan kunci mu. Fungsi Increment() akan mengunci mu dan menambah kiraan sebanyak 1. Fungsi Value() juga akan mengunci mu dan mengembalikan nilai kiraan. Ini memastikan bahawa penunjuk tidak akan luput apabila berbilang goroutine mengakses pembolehubah kiraan.

Kesimpulan

Walaupun Golang mengenakan sekatan ke atas operasi penunjuk, masalah ketidaksahihan penunjuk masih wujud. Di Golang, ketidaksahihan penunjuk biasanya berlaku kerana ruang memori yang ditunjuk oleh penunjuk dikitar semula atau dialihkan. Penyelesaian termasuk mengelakkan alamat pemulangan pembolehubah tempatan, atau menggunakan kunci untuk melindungi penunjuk dalam persekitaran berbilang benang. Jika kita boleh menggunakan penunjuk dengan betul dan menggunakan penyelesaian yang sesuai, kita boleh mengelakkan masalah ketidaksahihan penunjuk.

Atas ialah kandungan terperinci Bincangkan punca dan penyelesaian kegagalan penunjuk di Golang. Untuk maklumat lanjut, sila ikut artikel berkaitan lain di laman web China PHP!

Kenyataan:
Kandungan artikel ini disumbangkan secara sukarela oleh netizen, dan hak cipta adalah milik pengarang asal. Laman web ini tidak memikul tanggungjawab undang-undang yang sepadan. Jika anda menemui sebarang kandungan yang disyaki plagiarisme atau pelanggaran, sila hubungi admin@php.cn