Mengapa kompiler tidak secara otomatis memasukkan deallocations?

63

Dalam bahasa seperti C, programmer diharapkan memasukkan panggilan gratis. Mengapa kompiler tidak melakukan ini secara otomatis? Manusia melakukannya dalam jumlah waktu yang wajar (mengabaikan serangga), jadi itu tidak mustahil.

EDIT: Untuk referensi di masa mendatang, berikut adalah diskusi lain yang memiliki contoh menarik.

Milton Silva
sumber
125
Dan itu, anak-anak, itulah sebabnya kami mengajarkan Anda teori komputabilitas. ;)
Raphael
7
Ini bukan masalah komputasi karena manusia tidak dapat memutuskan dalam semua kasus juga. Ini masalah kelengkapan; pernyataan deallokasi berisi informasi yang, jika dihapus, tidak dapat sepenuhnya dipulihkan oleh analisis kecuali analisis itu mencakup informasi tentang lingkungan penyebaran dan operasi yang diharapkan, yang tidak mengandung kode sumber C.
Nat
41
Tidak, ini masalah komputasi. Tidak dapat dipastikan apakah sepotong memori yang diberikan harus dialokasikan ulang. Untuk program tetap, tidak ada input pengguna atau gangguan eksternal lainnya.
Andrej Bauer
1
Komentar bukan untuk diskusi panjang; percakapan ini telah dipindahkan ke obrolan . Semua komentar yang tidak secara khusus menjawab pertanyaan dan bagaimana cara meningkatkannya akan dihapus saat dilihat.
Raphael
2
@BorisTreukhov, bawa ke ruang obrolan. Tidak, saya tidak berpikir Andrej mengatakan bahwa analisis pelarian adalah "tidak mungkin" (meskipun menentukan apa artinya dalam konteks ini agak tidak jelas bagi saya). Analisis pelarian yang sangat tepat tidak dapat dipungkiri. Untuk semua: bawa ke ruang obrolan . Harap hanya mengirim komentar di sini yang ditujukan untuk meningkatkan pertanyaan - diskusi dan komentar lain harus diposting di ruang obrolan.
DW

Jawaban:

81

Karena tidak diputuskan apakah program akan menggunakan memori lagi. Ini berarti bahwa tidak ada algoritma yang dapat menentukan dengan benar kapan harus memanggil free()semua kasus, yang berarti bahwa setiap kompiler yang mencoba melakukan hal ini tentu akan menghasilkan beberapa program dengan kebocoran memori dan / atau beberapa program yang terus menggunakan memori yang telah dibebaskan. Bahkan jika Anda memastikan bahwa kompiler Anda tidak pernah melakukan yang kedua dan memungkinkan programmer untuk memasukkan panggilan untuk free()memperbaiki bug tersebut, mengetahui kapan harus memanggil free()kompiler itu akan lebih sulit daripada mengetahui kapan harus menelepon free()saat menggunakan kompiler yang tidak mencoba untuk membantu.

David Richerby
sumber
12
Kami memiliki pertanyaan yang mencakup kemampuan manusia untuk menyelesaikan masalah yang tidak dapat dipastikan . Saya tidak bisa memberikan contoh program yang akan dikompilasi secara tidak benar karena itu tergantung pada algoritma apa yang digunakan oleh kompiler. Tetapi setiap algoritma akan menghasilkan output yang salah untuk banyak program yang berbeda.
David Richerby
1
Komentar bukan untuk diskusi panjang; percakapan ini telah dipindahkan ke obrolan .
Gilles 'SO- stop being evil'
2
Kawan, bawa untuk ngobrol . Segala sesuatu yang tidak berhubungan langsung dengan jawaban itu sendiri dan bagaimana hal itu dapat diperbaiki akan dihapus.
Raphael
2
Banyak hal yang dilakukan penyusun dengan senang hati tidak dapat diputuskan secara umum; kita tidak akan mendapatkan apa pun di dunia kompiler jika kita selalu menyerah pada teorema Rice.
Tikhon Jelvis
3
Ini tidak relevan. Jika itu tidak dapat diputuskan untuk semua penyusun, itu juga tidak dapat diputuskan untuk semua manusia. Namun kami mengharapkan manusia untuk memasukkan free()dengan benar.
Paul Draper
53

Seperti yang dikatakan David Richerby dengan benar, masalahnya secara umum tidak dapat dipastikan. Keberanian objek adalah properti global dari program, dan mungkin secara umum bergantung pada input ke program.

Bahkan pengumpulan sampah dinamis yang presisi adalah masalah yang tidak dapat dipastikan! Semua pengumpul sampah dunia nyata menggunakan keterjangkauan sebagai perkiraan konservatif apakah objek yang dialokasikan akan dibutuhkan di masa depan. Ini adalah pendekatan yang baik, tetapi ini adalah perkiraan.

Tapi itu hanya berlaku secara umum. Salah satu solusi paling terkenal dalam bisnis ilmu komputer adalah "secara umum tidak mungkin, oleh karena itu kita tidak dapat melakukan apa-apa". Sebaliknya, ada banyak kasus di mana dimungkinkan untuk membuat kemajuan.

Implementasi berdasarkan penghitungan referensi sangat dekat dengan "kompilasi penempatan deallocations" sehingga sulit untuk membedakannya. LLVM 's penghitungan referensi otomatis (digunakan dalam Objective-C dan Swift ) adalah contoh yang terkenal.

Inferensi wilayah dan pengumpulan sampah waktu adalah area penelitian aktif saat ini. Ternyata jauh lebih mudah dalam bahasa deklaratif seperti ML dan Merkurius , di mana Anda tidak dapat memodifikasi objek setelah itu dibuat.

Sekarang, pada topik manusia, ada tiga cara utama manusia mengelola alokasi hidup secara manual:

  1. Dengan memahami program dan masalahnya. Manusia dapat menempatkan objek dengan masa hidup yang serupa di objek alokasi yang sama, misalnya. Penyusun dan pemulung harus menyimpulkan hal ini, tetapi manusia memiliki informasi yang lebih tepat.
  2. Dengan secara selektif menggunakan pembukuan non-lokal (mis. Penghitungan referensi) atau teknik alokasi khusus lainnya (misalnya zona) hanya bila diperlukan. Sekali lagi, manusia dapat mengetahui hal ini di mana penyusun harus menyimpulkannya.
  3. Sangat. Bagaimanapun, semua orang tahu tentang program yang dikerahkan di dunia nyata yang memiliki kebocoran lambat. Atau jika tidak, kadang-kadang program dan API internal perlu direstrukturisasi di sekitar masa pakai memori, mengurangi usabilitas dan modularitas.
Nama samaran
sumber
Komentar bukan untuk diskusi panjang. Jika Anda ingin mendiskusikan deklaratif vs fungsional, silakan lakukan dalam obrolan .
Gilles 'SANGAT berhenti menjadi jahat'
2
Sejauh ini, ini adalah jawaban terbaik untuk pertanyaan (yang terlalu banyak jawaban bahkan tidak menjawab) Anda bisa menambahkan referensi ke karya perintis Hans Boehm pada GC konseervatif : en.wikipedia.org/wiki/Boehm_garbage_collector . Hal lain yang menarik adalah bahwa data liveness (atau kegunaan dalam arti luas) dapat didefinisikan sehubungan dengan semantik abstrak atau model eksekusi. Tapi topiknya sangat luas.
babou
29

Ini masalah ketidaklengkapan, bukan masalah ketidakpastian

Meskipun benar bahwa penempatan optimal dari pernyataan deallokasi tidak dapat diputuskan, itu bukan masalah di sini. Karena tidak dapat ditentukan untuk manusia dan penyusun, mustahil untuk selalu memilih penempatan deallokasi optimal secara sadar, terlepas dari apakah itu proses manual atau otomatis. Dan karena tidak ada yang sempurna, kompiler yang cukup mahir harus mampu mengalahkan manusia dalam memperkirakan penempatan yang optimal. Jadi, ketidakpastian itu bukan alasan mengapa kita membutuhkan pernyataan deallokasi eksplisit .

Ada kasus di mana pengetahuan eksternal menginformasikan penempatan pernyataan deallokasi. Menghapus pernyataan itu sama dengan menghapus bagian dari logika operasional, dan meminta kompiler untuk secara otomatis menghasilkan logika itu sama dengan memintanya untuk menebak apa yang Anda pikirkan.

Misalnya, Anda menulis Read-Evaluate-Print-Loop (REPL) : pengguna mengetikkan perintah, dan program Anda mengeksekusinya. Pengguna dapat mengalokasikan / membatalkan alokasi memori dengan mengetikkan perintah ke dalam REPL Anda. Kode sumber Anda akan menentukan apa yang harus dilakukan REPL untuk setiap perintah pengguna yang mungkin, termasuk deallokasi ketika pengguna mengetikkan perintah untuk itu.

Tetapi jika kode sumber C tidak memberikan perintah eksplisit untuk deallokasi, maka kompiler perlu menyimpulkan bahwa ia harus melakukan dellokasi ketika pengguna memasukkan perintah yang sesuai ke dalam REPL. Apakah perintah itu "membatalkan alokasi", "bebas", atau yang lain? Kompiler tidak memiliki cara untuk mengetahui apa yang Anda inginkan dari perintah. Bahkan jika Anda memprogram dalam logika untuk mencari kata perintah itu dan REPL menemukannya, kompiler tidak memiliki cara untuk mengetahui bahwa itu harus menanggapi dengan deallokasi kecuali Anda secara eksplisit mengatakannya dalam kode sumber.

tl; dr Masalahnya adalah kode sumber C tidak memberikan kompiler pengetahuan eksternal. Ketidakpastian bukan masalah karena itu ada apakah prosesnya manual atau otomatis.

Nat
sumber
3
Komentar bukan untuk diskusi panjang; percakapan ini telah dipindahkan ke obrolan . Semua komentar lebih lanjut yang tidak secara khusus membahas kekurangan dari jawaban ini dan bagaimana mereka dapat diperbaiki akan dihapus pada pandangan.
Raphael
23

Saat ini, tidak ada jawaban yang diposting sepenuhnya benar.

Mengapa kompiler tidak secara otomatis memasukkan deallocations?

  1. Beberapa melakukannya. (Saya akan jelaskan nanti.)

  2. Secara sepele, Anda dapat menelepon free()tepat sebelum program keluar. Tetapi ada kebutuhan tersirat dalam pertanyaan Anda untuk menelepon free()sesegera mungkin.

  3. Masalah kapan harus memanggil free()dalam setiap program C segera setelah memori tidak dapat dijangkau tidak dapat ditentukan, yaitu untuk algoritma apa pun yang memberikan jawaban dalam waktu yang terbatas, ada kasus yang tidak tercakup. Ini - dan banyak ketidakpastian lain dari program yang sewenang-wenang - dapat dibuktikan dari Masalah Pemutusan Hubungan .

  4. Masalah yang tidak dapat diputuskan tidak selalu dapat diselesaikan dalam waktu yang terbatas oleh algoritma apa pun, apakah itu kompilator atau manusia.

  5. Manusia (mencoba) menulis dalam himpunan bagian dari program C yang dapat diverifikasi untuk kebenaran memori dengan algoritma mereka (sendiri).

  6. Beberapa bahasa mencapai # 1 dengan membangun # 5 ke dalam kompiler. Mereka tidak mengizinkan program dengan penggunaan alokasi memori yang sewenang-wenang, melainkan bagian yang dapat ditentukan dari mereka. Foth dan Rust adalah dua contoh bahasa yang memiliki alokasi memori lebih ketat daripada bahasa C malloc(), yang dapat (1) mendeteksi jika suatu program ditulis di luar set yang dapat ditentukan (2) menyisipkan deallokasi secara otomatis.

Paul Draper
sumber
1
Saya mengerti bagaimana Rust melakukannya. Tetapi saya tidak pernah mendengar Forth yang melakukan ini. Bisakah Anda menguraikan?
Milton Silva
2
@MiltonSilva, Forth - setidaknya implementasi yang paling mendasar dan asli - hanya memiliki tumpukan, bukan tumpukan. Itu membuat alokasi / deallokasi memindahkan pointer tumpukan panggilan, tugas yang dapat dilakukan dengan mudah oleh kompiler. Keempat dibuat untuk menargetkan perangkat keras yang sangat sederhana, dan kadang-kadang hanya memori non-dinamis yang bisa dikerjakan. Ini jelas bukan solusi yang bisa diterapkan untuk program non-sepele.
Paul Draper
10

"Manusia melakukannya, jadi bukan tidak mungkin" adalah kesalahan yang terkenal. Kita tidak perlu memahami (apalagi mengendalikan) hal-hal yang kita buat - uang adalah contoh umum. Kita cenderung melebih-lebihkan (kadang-kadang secara dramatis) peluang keberhasilan kita dalam masalah teknologi, terutama ketika faktor manusia tampaknya tidak ada.

Kinerja manusia dalam pemrograman komputer sangat buruk , dan studi ilmu komputer (kurang dalam banyak program pendidikan profesional) membantu memahami mengapa masalah ini tidak memiliki perbaikan yang sederhana. Kita mungkin suatu hari, mungkin tidak terlalu jauh, digantikan oleh kecerdasan buatan pada pekerjaan. Meski begitu, tidak akan ada algoritma umum yang mendapatkan alokasi yang benar, secara otomatis, setiap saat.

André Souza Lemos
sumber
1
Kekeliruan menerima premis kesalahan manusia namun menganggap bahwa mesin pemikiran yang diciptakan manusia mungkin masih sempurna (yaitu lebih baik daripada manusia) kurang dikenal tetapi lebih menarik. Satu-satunya asumsi dari mana tindakan dapat dilanjutkan adalah bahwa pikiran manusia memiliki potensi untuk dikomputasi dengan sempurna.
Wildcard
1. Saya tidak pernah mengatakan bahwa mesin berpikir mungkin sempurna. Lebih baik daripada manusia apa adanya, dalam banyak kasus. 2. Harapan kesempurnaan (bahkan potensi) sebagai prasyarat untuk bertindak adalah absurditas.
André Souza Lemos
"Kita mungkin suatu hari, mungkin tidak terlalu jauh, digantikan oleh kecerdasan buatan pada pekerjaan." Ini, khususnya, tidak masuk akal. Manusia adalah sumber niat dalam sistem. Tanpa manusia, tidak ada tujuan untuk sistem. "Kecerdasan Buatan" dapat didefinisikan sebagai kemunculan keputusan cerdas saat ini oleh mesin, yang sebenarnya disebabkan oleh keputusan cerdas seorang programmer atau perancang sistem di masa lalu. Jika tidak ada pemeliharaan (yang harus dilakukan oleh seseorang), AI (atau sistem apa pun yang dibiarkan tidak terdeteksi dan sepenuhnya otomatis) akan gagal.
Wildcard
Niat, pada manusia seperti pada mesin, selalu datang dari luar .
André Souza Lemos
Sama sekali tidak benar. (Dan juga, "luar" tidak mendefinisikan sumber. ) Entah Anda menyatakan maksud itu tidak benar-benar ada, atau Anda menyatakan niat itu ada tetapi tidak datang dari mana pun. Mungkin Anda percaya bahwa niat bisa ada terlepas dari tujuan? Dalam hal ini Anda salah mengerti kata "niat." Either way, demonstrasi secara langsung akan segera berubah pikiran tentang subjek ini. Saya akan menyerah setelah komentar ini karena kata-kata saja tidak dapat menghasilkan pemahaman tentang "niat," sehingga diskusi lebih lanjut di sini tidak ada gunanya.
Wildcard
9

Kurangnya manajemen memori otomatis adalah fitur bahasa.

C tidak seharusnya menjadi alat untuk menulis perangkat lunak dengan mudah. Ini adalah alat untuk membuat komputer melakukan apa pun yang Anda perintahkan. Itu termasuk mengalokasikan dan membatalkan alokasi memori pada saat yang Anda pilih. C adalah bahasa tingkat rendah yang Anda gunakan saat Anda ingin mengontrol komputer dengan tepat, atau ketika Anda ingin melakukan sesuatu dengan cara yang berbeda dari apa yang diharapkan oleh perancang perpustakaan bahasa / standar.

Jouni Sirén
sumber
Komentar bukan untuk diskusi panjang; percakapan ini telah dipindahkan ke obrolan .
DW
2
Bagaimana ini menjawab pertanyaan (bagian CS dari)?
Raphael
6
@Raphael Ilmu komputer tidak berarti bahwa kita harus mencari jawaban teknis yang tidak jelas. Kompiler melakukan banyak hal yang tidak mungkin dalam kasus umum. Jika kita menginginkan manajemen memori otomatis, kita dapat mengimplementasikannya dengan banyak cara. C tidak melakukannya, karena itu tidak seharusnya dilakukan.
Jouni Sirén
9

Masalahnya sebagian besar adalah artefak bersejarah, bukan ketidakmungkinan implementasi.

Cara kebanyakan kompiler C membuat kode adalah sehingga kompiler hanya melihat setiap file sumber pada satu waktu; tidak pernah melihat keseluruhan program sekaligus. Ketika satu file sumber memanggil fungsi dari file sumber lain atau pustaka, semua kompiler melihat adalah file header dengan jenis fungsi yang dikembalikan, bukan kode sebenarnya dari fungsi tersebut. Ini berarti ketika ada fungsi yang mengembalikan pointer, kompiler tidak memiliki cara untuk mengetahui apakah memori yang menunjuk pointer perlu dibebaskan atau tidak. Informasi untuk memutuskan yang tidak ditampilkan ke kompiler pada saat itu. Seorang programmer manusia, di sisi lain, bebas untuk mencari kode sumber fungsi atau dokumentasi untuk mengetahui apa yang perlu dilakukan dengan pointer.

Jika Anda melihat ke bahasa tingkat rendah yang lebih modern seperti C ++ 11 atau Rust Anda akan menemukan bahwa mereka sebagian besar memecahkan masalah dengan membuat kepemilikan memori eksplisit dalam jenis pointer. Dalam C + + Anda akan menggunakan unique_ptr<T>alih - alih dataran T*untuk menahan memori dan unique_ptr<T>memastikan bahwa memori akan dibebaskan ketika objek mencapai ujung lingkup, tidak seperti dataran T*. Programmer dapat menyerahkan memori dari satu unique_ptr<T>ke yang lain, tetapi hanya ada satu unique_ptr<T>menunjuk pada memori. Jadi, selalu jelas siapa yang memiliki memori dan kapan perlu dibebaskan.

C ++, untuk alasan kompatibilitas ke belakang, masih memungkinkan manajemen memori manual gaya lama dan dengan demikian penciptaan bug atau cara untuk menghindari perlindungan a unique_ptr<T>. Rust bahkan lebih ketat karena memberlakukan aturan kepemilikan memori melalui kesalahan kompiler.

Adapun keraguan, masalah penghentian dan sejenisnya, ya, jika Anda tetap pada semantik C tidak mungkin untuk memutuskan untuk semua program ketika memori harus dibebaskan. Namun untuk sebagian besar program aktual, bukan latihan akademis atau perangkat lunak kereta, sangat mungkin untuk memutuskan kapan harus bebas dan kapan tidak. Bagaimanapun, itulah satu-satunya alasan mengapa manusia dapat mengetahui kapan harus bebas atau tidak.

Grumbel
sumber
Komentar bukan untuk diskusi panjang; percakapan ini telah dipindahkan ke obrolan .
Raphael
6

Jawaban lain berfokus pada apakah mungkin untuk melakukan pengumpulan sampah, beberapa detail tentang bagaimana hal itu dilakukan, dan beberapa masalah.

Salah satu masalah yang belum dibahas adalah keterlambatan pengumpulan sampah yang tak terhindarkan. Di C, ketika programmer memanggil free (), memori itu segera tersedia untuk digunakan kembali. (Setidaknya dalam teori!) Jadi seorang programmer dapat membebaskan struktur 100MB mereka, mengalokasikan struktur 100MB lain milidetik kemudian, dan mengharapkan penggunaan memori secara keseluruhan tetap sama.

Ini tidak benar dengan pengumpulan sampah. Sistem pengumpulan sampah memiliki beberapa keterlambatan dalam mengembalikan memori yang tidak digunakan ke tumpukan, dan ini bisa menjadi signifikan. Jika struktur 100MB Anda keluar dari ruang lingkup, dan milidetik kemudian, program Anda membuat struktur 100MB lainnya, Anda dapat mengharapkan sistem Anda menggunakan 200MB untuk periode yang singkat. "Periode singkat" itu mungkin milidetik atau detik tergantung pada sistem, tetapi masih ada penundaan.

Jika Anda menjalankan pada PC dengan gigs of RAM dan memori virtual, tentu saja Anda mungkin tidak akan pernah melihat ini. Jika Anda menjalankan sistem dengan sumber daya yang lebih terbatas (katakanlah, sistem yang disematkan atau telepon), ini adalah sesuatu yang perlu Anda perhatikan dengan serius. Ini bukan hanya teoretis - Saya pribadi telah melihat ini membuat masalah (seperti menabrak jenis perangkat masalah) ketika bekerja pada sistem WinCE menggunakan .NET Compact Framework dan berkembang di C #.

Graham
sumber
Anda bisa secara teori menjalankan GC sebelum setiap alokasi.
adrianN
4
@ adrianN Tapi dalam praktiknya ini tidak dilakukan karena itu akan mental. Poin Graham masih berdiri: GCs selalu mengeluarkan overhead yang besar, baik dalam hal runtime atau dalam hal memori surplus yang diperlukan. Anda dapat mengubah keseimbangan ini menjadi ekstrem, tetapi pada dasarnya Anda tidak dapat menghapus overhead.
Konrad Rudolph
"Penundaan" ketika memori dibebaskan lebih merupakan masalah dalam sistem memori virtual daripada dalam sistem dengan sumber daya terbatas. Dalam kasus sebelumnya, mungkin lebih baik bagi sebuah program untuk menggunakan 100MB dari 200MB bahkan jika sistem memiliki 200MB tersedia , tetapi dalam kasus terakhir tidak akan ada manfaat untuk menjalankan GC lebih awal dari yang dibutuhkan kecuali penundaan akan lebih diterima selama beberapa bagian dari kode daripada yang lain.
supercat
Saya gagal melihat bagaimana upaya ini untuk menjawab pertanyaan (bagian CS dari).
Raphael
1
@Raphael Saya telah menjelaskan masalah yang diakui dengan prinsip pengumpulan sampah, yang (atau harus) diajarkan di CS sebagai salah satu kelemahan mendasarnya. Saya bahkan telah memberikan pengalaman pribadi saya setelah melihat ini dalam praktik, untuk menunjukkan bahwa itu bukan masalah teoritis semata. Jika Anda gagal memahami sesuatu tentang ini, saya senang berbicara dengan Anda untuk meningkatkan pengetahuan Anda tentang subjek ini.
Graham
4

Pertanyaannya menganggap deallokasi adalah sesuatu yang seharusnya disimpulkan oleh programmer dari bagian lain dari kode sumber. Ini bukan. "Pada titik ini dalam program, referensi memori FOO tidak berguna lagi" adalah informasi yang hanya diketahui dalam pikiran programmer sampai itu dikodekan ke dalam (dalam bahasa prosedural) pernyataan deallokasi.

Secara teori tidak berbeda dari baris kode lainnya. Mengapa kompiler tidak secara otomatis memasukkan "Pada titik ini dalam program, periksa register BAR untuk input" atau "jika pemanggilan fungsi mengembalikan nol, keluar dari subrutin saat ini" ? Dari sudut pandang kompiler alasannya adalah "ketidaklengkapan", seperti yang ditunjukkan dalam jawaban ini . Tetapi setiap program mengalami ketidaklengkapan ketika programmer belum menceritakan semua yang dia tahu.

Dalam kehidupan nyata, deallocation adalah pekerjaan kasar atau boilerplate; otak kita mengisinya secara otomatis dan menggerutu tentang hal itu, dan sentimen "kompiler dapat melakukannya dengan baik atau lebih baik" adalah benar. Namun secara teori, bukan itu masalahnya, walaupun untungnya bahasa lain memberi kita lebih banyak pilihan teori.

Travis Wilson
sumber
4
"'Pada titik ini dalam program, referensi memori FOO tidak berguna lagi' adalah informasi yang hanya diketahui dalam pikiran programmer" - itu jelas salah. a) Bagi banyak FOO, mudah untuk mengetahuinya, misalnya variabel lokal dengan semantik nilai. b) Anda menyarankan agar programmer mengetahui hal ini, selalu, yang jelas merupakan asumsi yang terlalu optimis; jika itu benar, kami tidak akan memiliki bug yang parah karena penanganan memori yang buruk adalah perangkat lunak yang sangat penting untuk keamanan. Yang, sayangnya, kita lakukan.
Raphael
Saya hanya menyarankan bahwa bahasa itu dirancang untuk kasus-kasus di mana programmer tidak tahu FOO tidak berguna lagi. Saya setuju, jelas, ini biasanya tidak benar, dan itulah sebabnya kita perlu memiliki analisis statis dan / atau pengumpulan sampah. Yang mana, hore, kita lakukan. Tetapi pertanyaan OP adalah, kapan hal-hal itu tidak seberharga deallocs kode tangan?
Travis Wilson
4

Apa yang dilakukan: Ada pengumpulan sampah, dan ada kompiler yang menggunakan penghitungan referensi (Objective-C, Swift). Mereka yang melakukan penghitungan referensi membutuhkan bantuan dari programmer dengan menghindari siklus referensi yang kuat.

The nyata jawaban "mengapa" adalah bahwa penulis compiler belum tahu cara yang cukup baik dan cukup cepat untuk membuatnya dapat digunakan dalam kompilator. Karena penulis kompiler biasanya cukup pintar, Anda dapat menyimpulkan bahwa sangat, sangat sulit untuk menemukan cara yang cukup baik dan cukup cepat.

Salah satu alasan mengapa hal itu sangat, sangat sulit tentu saja tidak dapat diputuskan. Dalam ilmu komputer, ketika kita berbicara tentang "decidability" yang kita maksudkan adalah "membuat keputusan yang tepat". Pemrogram manusia tentu saja dapat dengan mudah memutuskan di mana harus mengalokasikan memori, karena mereka tidak terbatas pada keputusan yang benar . Dan mereka sering membuat keputusan yang salah.

gnasher729
sumber
Saya gagal melihat kontribusi di sini.
babou
3

Dalam bahasa seperti C, programmer diharapkan memasukkan panggilan gratis. Mengapa kompiler tidak melakukan ini secara otomatis?

Karena masa pakai memory block adalah keputusan programmer, bukan compiler.

Itu dia. Ini adalah desain C. Compiler tidak dapat mengetahui apa tujuan mengalokasikan blok memori. Manusia dapat melakukannya, karena mereka tahu tujuan setiap blok memori dan kapan tujuan ini dilayani sehingga dapat dibebaskan. Itu bagian dari desain program yang sedang ditulis.

C adalah bahasa tingkat rendah, jadi contoh untuk melewatkan blok memori Anda ke proses lain atau bahkan ke prosesor lain cukup sering. Dalam kasus ekstrim, seorang programmer dapat dengan sengaja mengalokasikan sejumlah memori dan tidak pernah menggunakannya lagi hanya untuk memberikan tekanan memori pada bagian lain dari sistem. Compiler tidak memiliki cara untuk mengetahui apakah blok tersebut masih diperlukan.

Agent_L
sumber
-1

Dalam bahasa seperti C, programmer diharapkan memasukkan panggilan gratis. Mengapa kompiler tidak melakukan ini secara otomatis?

Dalam C dan banyak bahasa lain, memang ada fasilitas untuk membuat kompiler melakukan hal yang sama dalam hal ini di mana hal itu jelas pada waktu kompilasi ketika harus dilakukan: penggunaan variabel durasi otomatis (yaitu variabel lokal biasa) . Compiler bertanggung jawab untuk mengatur ruang yang cukup untuk variabel-variabel tersebut, dan untuk melepaskan ruang itu ketika masa hidup mereka (yang didefinisikan dengan baik) berakhir.

Dengan array panjang variabel menjadi fitur C sejak C99, objek durasi otomatis melayani, pada prinsipnya, secara substansial semua fungsi di C yang dilakukan objek yang secara dinamis dialokasikan untuk durasi yang dikomputasi. Dalam praktiknya, tentu saja, implementasi C dapat menempatkan batasan praktis yang signifikan dalam penggunaan VLA - yaitu ukurannya mungkin terbatas sebagai akibat dialokasikan pada tumpukan - tetapi ini adalah pertimbangan implementasi, bukan pertimbangan desain bahasa.

Objek-objek yang tujuan penggunaannya tidak memberi mereka durasi otomatis adalah mereka yang seumur hidupnya tidak dapat ditentukan pada waktu kompilasi.

PellMel
sumber