Katakanlah saya memiliki kode C berikut:
int main () {
int *p = malloc(10 * sizeof *p);
*p = 42;
return 0; //Exiting without freeing the allocated memory
}
Ketika saya mengkompilasi dan menjalankan program C itu, yaitu setelah mengalokasikan beberapa ruang dalam memori, apakah memori yang saya alokasikan akan tetap dialokasikan (yaitu pada dasarnya mengambil ruang) setelah saya keluar dari aplikasi dan prosesnya berakhir?
c
memory-management
Andreas Grech
sumber
sumber
Jawaban:
Itu tergantung pada sistem operasi. Mayoritas sistem operasi modern (dan semua sistem operasi utama) akan membebaskan memori yang tidak dibebaskan oleh program saat program berakhir.
Mengandalkan ini adalah praktik yang buruk dan lebih baik membebaskannya secara eksplisit. Masalahnya bukan hanya kode Anda terlihat buruk. Anda mungkin memutuskan ingin mengintegrasikan program kecil Anda ke program yang lebih besar dan berjalan lama. Kemudian beberapa saat kemudian Anda harus menghabiskan waktu berjam-jam melacak kebocoran memori.
Mengandalkan fitur sistem operasi juga membuat kode kurang portabel.
sumber
Secara umum, sistem operasi serba guna modern melakukan pembersihan setelah proses dihentikan . Hal ini diperlukan karena alternatifnya adalah sistem kehilangan sumber daya dari waktu ke waktu dan memerlukan boot ulang karena program yang ditulis dengan buruk atau hanya memiliki bug yang jarang terjadi yang membocorkan sumber daya.
Membuat program Anda secara eksplisit membebaskan sumber dayanya bisa menjadi praktik yang baik karena berbagai alasan, seperti:
Namun, berikut ini alasan untuk melewati ruang kosong: pematian yang efisien . Misalnya, aplikasi Anda berisi cache yang besar di memori. Jika saat keluar, ia melewati seluruh struktur cache dan membebaskannya satu per satu, itu tidak memiliki tujuan yang berguna dan membuang sumber daya. Terutama, pertimbangkan kasus di mana halaman memori yang berisi cache Anda telah ditukar ke disk oleh sistem operasi; dengan menjalankan struktur dan membebaskannya, Anda membawa semua halaman itu kembali ke memori sekaligus , membuang-buang waktu dan energi yang signifikan tanpa manfaat yang sebenarnya, dan bahkan mungkin menyebabkan program lain di sistem ditukar!
Sebagai contoh terkait, ada server berkinerja tinggi yang bekerja dengan membuat proses untuk setiap permintaan, lalu keluar setelah selesai; dengan ini berarti mereka bahkan tidak perlu melacak alokasi memori , dan tidak pernah melakukan pembebasan atau pengumpulan sampah sama sekali, karena semuanya akan hilang begitu saja kembali ke memori bebas sistem operasi pada akhir proses. (Hal yang sama dapat dilakukan dalam proses menggunakan pengalokasi memori khusus, tetapi membutuhkan pemrograman yang sangat hati-hati; pada dasarnya membuat gagasan sendiri tentang "proses ringan" dalam proses OS.)
sumber
Saya minta maaf untuk memposting begitu lama setelah posting terakhir ke utas ini.
Satu poin tambahan. Tidak semua program berhasil keluar dengan baik. Crash dan ctrl-C, dll. Akan menyebabkan program keluar dengan cara yang tidak terkontrol. Jika OS Anda tidak membebaskan heap Anda, membersihkan tumpukan Anda, menghapus variabel statis, dll, Anda pada akhirnya akan merusak sistem Anda karena kebocoran memori atau lebih buruk.
Selain menarik untuk ini, crash / break di Ubuntu, dan saya menduga semua OS modern lainnya, memang memiliki masalah dengan sumber daya yang "ditangani. Soket, file, perangkat, dll. Dapat tetap" terbuka "ketika program berakhir / crash. Ini juga praktik yang baik untuk menutup apa pun dengan "pegangan" atau "deskriptor" sebagai bagian dari pembersihan sebelum keluar dengan anggun.
Saya sedang mengembangkan program yang sangat banyak menggunakan soket. Ketika saya terjebak dalam hang, saya harus menekan ctrl-c untuk melepaskannya, sehingga membuat soket saya lepas. Saya menambahkan std :: vector untuk mengumpulkan daftar semua soket yang terbuka dan penangan sigaction yang menangkap sigint dan sigterm. Pawang menjalankan daftarnya dan menutup soketnya. Saya berencana membuat rutinitas pembersihan serupa untuk digunakan sebelum lemparan yang akan menyebabkan penghentian dini.
Ada yang mau mengomentari desain ini?
sumber
Apa yang terjadi di sini ( dalam OS modern ), adalah bahwa program Anda berjalan di dalam "proses" -nya sendiri. Ini adalah entitas sistem operasi yang diberkahi dengan ruang alamatnya sendiri, deskriptor file, dll.
malloc
Panggilan Anda mengalokasikan memori dari "heap", atau halaman memori yang tidak terisi yang ditetapkan untuk proses Anda.Ketika program Anda berakhir, seperti dalam contoh ini, semua sumber daya yang ditugaskan untuk proses Anda hanya didaur ulang / dihancurkan oleh sistem operasi. Dalam kasus memori, semua halaman memori yang ditetapkan untuk Anda hanya ditandai sebagai "bebas" dan didaur ulang untuk digunakan proses lain. Halaman adalah konsep tingkat yang lebih rendah daripada yang ditangani malloc-- sebagai hasilnya, spesifikasi malloc / free semuanya hanyut begitu semuanya dibersihkan.
Ini setara dengan moral, ketika Anda selesai menggunakan laptop dan ingin memberikannya kepada teman, Anda tidak perlu repot-repot menghapus setiap file satu per satu. Anda tinggal memformat hard drive.
Semua ini mengatakan, seperti yang dicatat oleh semua penjawab lainnya, mengandalkan ini bukanlah praktik yang baik:
sumber
Iya. OS membersihkan sumber daya. Nah ... NetWare versi lama tidak.
Sunting: Seperti yang ditunjukkan San Jacinto, pasti ada sistem (selain dari NetWare) yang tidak melakukan itu. Bahkan dalam program sekali pakai, saya mencoba membiasakan diri untuk membebaskan semua sumber daya hanya untuk mempertahankan kebiasaan itu.
sumber
Ya, sistem operasi melepaskan semua memori saat proses berakhir.
sumber
malloc
hanya bisa menjanjikan apa yang akan dilakukan C dengan memori; menurut desain, C tidak menjamin banyak hal tentang perilaku di luar C itu sendiri. Jika aplikasi mati secara tidak terduga, janji apa pun yang dibuat library waktu proses menjadi batal demi hukum, karena tidak lagi berlaku untuk memenuhi janji tersebut.Itu tergantung, sistem operasi biasanya akan membersihkannya untuk Anda, tetapi jika Anda mengerjakan misalnya perangkat lunak yang disematkan maka itu mungkin tidak dirilis.
Pastikan Anda membebaskannya, ini dapat menghemat banyak waktu nanti ketika Anda mungkin ingin mengintegrasikannya ke dalam proyek besar.
sumber
Itu sangat tergantung pada sistem operasi, tetapi untuk semua sistem operasi yang pernah Anda temui, alokasi memori akan hilang saat proses keluar.
sumber
Saya pikir pembebasan langsung adalah yang terbaik. Perilaku tidak terdefinisi adalah hal terburuk, jadi jika Anda memiliki akses sementara itu masih ditentukan dalam proses Anda, lakukanlah, ada banyak alasan bagus yang diberikan orang untuk itu.
Mengenai di mana, atau apakah, saya menemukan bahwa di W98, pertanyaan sebenarnya adalah 'kapan' (saya tidak melihat postingan yang menekankan hal ini). Program template kecil (untuk input MIDI SysEx, menggunakan berbagai ruang malloc'd) akan membebaskan memori di bit WM_DESTROY dari WndProc, tetapi ketika saya memindahkannya ke program yang lebih besar, program tersebut macet saat keluar. Saya berasumsi ini berarti saya mencoba membebaskan apa yang telah dibebaskan OS selama pembersihan yang lebih besar. Jika saya melakukannya di WM_CLOSE, lalu memanggil DestroyWindow (), semuanya bekerja dengan baik, keluar bersih instan.
Meskipun ini tidak persis sama dengan buffer MIDI, ada kesamaan yaitu yang terbaik adalah menjaga proses tetap utuh, bersihkan sepenuhnya, lalu keluar. Dengan potongan memori sederhana ini sangat cepat. Saya menemukan bahwa banyak buffer kecil bekerja lebih cepat dalam pengoperasian dan pembersihan dibandingkan buffer besar yang lebih sedikit.
Pengecualian mungkin ada, seperti yang dikatakan seseorang ketika menghindari menarik potongan memori besar kembali dari file swap pada disk, tetapi bahkan itu dapat diminimalkan dengan menyimpan lebih banyak, dan lebih kecil, ruang yang dialokasikan.
sumber