Seperti yang saya pahami, apa pun yang dibuat dengan alokasi , baru , atau salinan harus dirilis secara manual. Sebagai contoh:
int main(void) {
NSString *string;
string = [[NSString alloc] init];
/* use the string */
[string release];
}
Pertanyaan saya, bukankah ini sama validnya ?:
int main(void) {
NSAutoreleasePool *pool;
pool = [[NSAutoreleasePool alloc] init];
NSString *string;
string = [[[NSString alloc] init] autorelease];
/* use the string */
[pool drain];
}
objective-c
memory-management
nsautoreleasepool
foundationkit
James Sumners
sumber
sumber
an object
seharusnyaan object that is a subclass of NSObject or NSProxy and doesn't override -autorelease
.NSAutoreleasePool: tiriskan vs. lepaskan
Karena fungsi dari
drain
danrelease
tampaknya menyebabkan kebingungan, mungkin perlu dijelaskan di sini (meskipun hal ini tercakup dalam dokumentasi ...).Sebenarnya, dari perspektif gambaran besar
drain
adalah tidak setara denganrelease
:Dalam lingkungan yang dihitung referensi,
drain
melakukan operasi yang sama sepertirelease
, sehingga keduanya dalam pengertian itu setara. Untuk menekankan, ini berarti Anda tidak membocorkan kolam jika Anda menggunakandrain
daripadarelease
.Dalam lingkungan yang mengumpulkan sampah,
release
tidak ada operasi. Jadi itu tidak berpengaruh.drain
, di sisi lain, berisi petunjuk kepada kolektor bahwa ia harus "mengumpulkan jika diperlukan". Jadi dalam lingkungan pengumpulan sampah, penggunaandrain
membantu menyapu pengumpulan keseimbangan sistem.sumber
NSAutoreleasePool
. Ini karena kumpulan beroperasi seperti tumpukan. Membuat instance kumpulan akan mendorong kumpulan itu ke bagian atas tumpukan kumpulan rilis otomatis thread tersebut.-release
menyebabkan kumpulan tersebut keluar dari tumpukan DAN kumpulan apa pun yang didorong ke atasnya, tetapi untuk alasan apa pun tidak muncul.Seperti yang telah ditunjukkan, potongan kode kedua Anda sudah benar.
Saya ingin menyarankan cara yang lebih ringkas untuk menggunakan kumpulan autorelease yang berfungsi di semua lingkungan (penghitungan ref, GC, ARC) dan juga menghindari kebingungan pembuangan / rilis:
Dalam contoh di atas, harap perhatikan blok @autoreleasepool . Ini didokumentasikan di sini .
sumber
@autoreleasepool
blok dengan ARC.Tidak, kamu salah. Dokumentasi menyatakan dengan jelas bahwa di bawah non-GC, -drain setara dengan -release, yang berarti NSAutoreleasePool tidak akan bocor.
sumber
NSAutoreleasePool
: developer.apple.com/mac/library/documentation/Cocoa/Conceptual/…Apa yang saya baca dari Apple: "Di akhir blok kumpulan pelepasan otomatis, objek yang menerima pesan pelepasan otomatis di dalam blok akan dikirimi pesan rilis — sebuah objek menerima pesan rilis untuk setiap kali itu dikirim pesan pelepasan otomatis di dalam blok. "
https://developer.apple.com/library/mac/documentation/cocoa/conceptual/MemoryMgmt/Articles/mmAutoreleasePools.html
sumber
mengirim autorelease dan bukan rilis ke suatu objek akan memperpanjang masa pakai objek tersebut setidaknya hingga kumpulan itu sendiri dikosongkan (mungkin lebih lama jika objek tersebut dipertahankan kemudian). Sebuah objek dapat dimasukkan ke dalam pool yang sama beberapa kali, dalam hal ini objek menerima pesan rilis untuk setiap kali dimasukkan ke dalam pool.
sumber
Iya dan tidak. Anda akhirnya akan melepaskan memori string tetapi "membocorkan" objek NSAutoreleasePool ke dalam memori dengan menggunakan drain, bukan rilis jika Anda menjalankan ini di lingkungan sampah yang dikumpulkan (bukan yang dikelola memori). "Kebocoran" ini hanya membuat instance NSAutoreleasePool "tidak dapat dijangkau" seperti objek lain tanpa petunjuk kuat di bawah GC, dan objek tersebut akan dibersihkan saat GC berjalan, yang bisa jadi langsung setelah panggilan ke
-drain
:Jika tidak, ini mirip dengan
-release
berperilaku di bawah non-GC, ya. Seperti yang dinyatakan orang lain,-release
adalah tidak ada operasi di bawah GC, jadi satu-satunya cara untuk memastikan fungsi kumpulan dengan baik di bawah GC adalah melalui-drain
, dan di-drain
bawah non-GC bekerja persis seperti di-release
bawah non-GC, dan bisa dibilang mengkomunikasikan fungsinya dengan lebih jelas sebagai baik.Saya harus menunjukkan bahwa pernyataan Anda "apa pun yang dipanggil dengan new, alokasi, atau init" tidak boleh menyertakan "init" (tetapi harus menyertakan "copy"), karena "init" tidak mengalokasikan memori, ia hanya menyiapkan objek (konstruktor mode). Jika Anda menerima objek yang dialokasikan dan fungsi Anda hanya memanggil init seperti itu, Anda tidak akan melepaskannya:
Itu tidak menghabiskan lebih banyak memori daripada yang sudah Anda mulai (dengan asumsi init tidak membuat instance objek, tetapi Anda tidak bertanggung jawab untuk itu).
sumber
-[NSAutoreleasePool release]
di lingkungan yang dikumpulkan sampah adalah no-op.-[NSAutoreleasePool drain]
bekerja di lingkungan yang dihitung referensi dan dikumpulkan sampahnya.