Manajemen memori di Objective-C dan mengatur pointer ke nihil

Akankah penunjuk ke suatu objek menuju ke nil ketika hitungannya mencapai 0 atau ketika dealloc dipanggil? Mengapa atau mengapa tidak?


person SVA    schedule 09.01.2010    source sumber


Jawaban (4)


Tidak, itu tidak akan terjadi, karena dealokasi tidak memiliki kekuatan untuk mengubah penunjuk. Hal ini hanya dapat dilakukan jika Anda meneruskan pointer ke pointer.

Jika Anda ingin memastikannya disetel ke nihil, Anda harus melakukannya sendiri.

Beberapa orang menganggap ini sebagai praktik yang baik, beberapa menganggapnya membuang-buang waktu karena kode Anda harus disusun untuk tidak menggunakan pointer setelah deallokasi (sampai dialokasikan kembali).

Saya sebenarnya condong ke arah kelompok yang terakhir tetapi saya dapat melihat mengapa orang ingin melindungi diri mereka sendiri dari mengakses memori yang dibebaskan (pemrograman secara defensif jarang merupakan ide yang buruk).

person paxdiablo    schedule 09.01.2010
comment
Saya menyiapkan makro untuk melepaskan pointer dengan aman dan mengaturnya ke nil. - person notnoop; 09.01.2010
comment
+1 FYI, Saat menggunakan pengumpulan sampah, __weak pointer bersifat self-zeroing. Selain itu, menggunakan makro untuk melakukan hal ini bisa rawan kesalahan, seperti yang saya sebutkan dalam jawaban saya di bawah. - person Quinn Taylor; 09.01.2010
comment
Jika Anda tidak menyetel referensi ke nil saat Anda merilis, Leaks tidak akan dapat memberi tahu Anda bahwa ada kebocoran memori - lagi pula, sejauh menyangkut Leaks, Anda memiliki referensi yang valid, meskipun menurut Anda referensi tersebut adalah tidak berlaku lagi (retensi berlebihan). - person Kendall Helmstetter Gelner; 10.01.2010
comment
Poin bagus. Kasus ketika Anda masih menyimpan penunjuk valid yang tidak lagi Anda gunakan dianggap sebagai memori yang ditinggalkan, bukan kebocoran. Untungnya, kemungkinan besar Anda akan melihat alat untuk mendeteksi memori yang ditinggalkan di Instrumen versi mendatang... :-) - person Quinn Taylor; 15.04.2010

Di bawah model memori pelepasan-pelepasan normal, tidak. Dengan pengumpulan sampah yang diaktifkan, hal ini terjadi jika penunjuk dideklarasikan sebagai __weak (untuk objek Objective-C, defaultnya adalah __strong). Pengumpul sampah akan menghilangkan referensi lemah untuk Anda ketika referensi tersebut dibuang, sehingga ideal untuk menunjuk ke delegasi dan objek semi-sementara. Lihat juga NSPointerArray, NSMapTable dan NSHashTable dan juga dukungan mereka terhadap hubungan yang lemah. (CATATAN: Kita harus memahami bahwa referensi yang lemah tidak akan mencegah objek dikumpulkan dari sampah; referensi tersebut akan bernilai nol jika tidak ada referensi kuat yang menunjuk ke alamat yang sama. Lihat dokumen ini untuk ringkasan singkat tentang perilaku ini.)

Ada banyak manfaat lain dari pengumpulan sampah Objective-C, dan saya sangat menyarankan untuk menggunakannya jika Anda bisa. (Ini tersedia pada OS X 10.5+, namun tidak pada OS iPhone.) Peningkatan kinerja pada Snow Leopard sangat mengesankan, dan pada awalnya sudah sangat cepat.

Meski begitu, @darren punya satu poin bagus: biasanya merupakan praktik yang baik untuk menghilangkan variabel Anda sendiri saat merilis kontennya. Jika Anda ingin menghindari petunjuk yang menggantung ke objek yang dilepaskan secara berlebihan, cara terbaik Anda adalah menerapkan kebiasaan menghilangkan variabel sendiri. Itu tidak akan menimbulkan overhead runtime, dan dapat dibaca. Lebih penting lagi, menyetel variabel ke nil membantu sistem pengumpulan sampah bekerja paling efektif, karena ini menunjukkan memori yang dapat diambil kembali dengan aman. Kode tersebut juga akan berfungsi di kedua mode dengan sempurna.

Namun, saya biasanya tidak menghapus nilai di -dealloc karena memori yang Anda modifikasi akan diambil kembali, dan jika beberapa bagian kode lainnya mungkin mengalami kesalahan karena menggunakan nilai yang dilepaskan , mereka seharusnya tidak menggunakan objek yang tidak dialokasikan untuk memulai. (Hal ini sering terjadi ketika satu objek tidak dapat menyimpan objek lainnya dengan benar, dan objek tersebut tidak dialokasikan, meninggalkan penunjuk yang menjuntai.) Kemungkinan pengecualian untuk hal ini mungkin termasuk pembongkaran bertahap di mana referensi non-nil dapat menyebabkan masalah dalam dealloc itu sendiri, namun jenis perilaku ini umumnya tidak (dan tidak seharusnya) terjadi saat menghancurkan suatu objek.

person Quinn Taylor    schedule 09.01.2010

Saya tidak yakin apakah penunjuk mengarah ke nil atau hanya menunjuk ke data yang tidak valid, tetapi konvensi pengkodean yang baik untuk menetapkan variabel Anda ke nil setelah Anda melepaskannya.

person D.C.    schedule 09.01.2010
comment
+1 Ini adalah saran yang bagus, terutama untuk variabel instan dan statis, dan juga dua kali lipat dalam pengumpulan sampah, di mana Anda dapat secara tidak sengaja mengumpulkan referensi kuat ke memori yang tidak diperlukan yang tidak akan diambil kembali sesuai keinginan. Saya pikir beberapa orang hanya menginginkan solusi ajaib sehingga mereka tidak perlu memikirkan masalah ini. - person Quinn Taylor; 09.01.2010

Pikirkan situasi ini:

void *p = malloc (100);

while (someCondition)
{
    //  do something with p
}

free (p);

// p is not set to NULL for you, it still points to where it always did

Demikian pula, ketika objek Objective-C tidak dialokasikan, petunjuk apa pun ke objek tersebut masih menunjuk ke tempatnya semula. Hal ini menyebabkan kesalahan ketika objek lain dialokasikan ke ruang yang sama (atau bahkan jika tidak ada objek yang dialokasikan ke ruang yang sama).

person dreamlax    schedule 09.01.2010