Saya sering mengalami kebocoran memori. Biasanya saat aku malloc
-ing seperti tidak ada hari esok, atau tergantungFILE *
seperti cucian kotor. Saya biasanya berasumsi (baca: berharap dengan putus asa) bahwa semua memori dibersihkan setidaknya ketika program berakhir. Adakah situasi di mana memori yang bocor tidak akan dikumpulkan saat program dihentikan, atau macet?
Jika jawabannya sangat bervariasi dari satu bahasa ke bahasa lain, maka mari kita fokus pada C (++).
Perhatikan penggunaan hiperbolik frasa, 'seperti tidak ada hari esok', dan 'menjuntai ... seperti cucian kotor'. Tidak aman * malloc
dapat melukai orang yang Anda cintai. Juga, harap berhati-hati dengan cucian kotor.
c++
c
memory
memory-leaks
DilithiumMatrix
sumber
sumber
calloc
seperti tidak ada hari esok. Luar biasa.Jawaban:
Tidak. Sistem operasi membebaskan semua sumber daya yang dimiliki oleh proses ketika mereka keluar.
Ini berlaku untuk semua sumber daya yang dikelola sistem operasi: memori, file terbuka, koneksi jaringan, pegangan jendela ...
Meskipun demikian, jika program berjalan pada sistem tertanam tanpa sistem operasi, atau dengan sistem operasi yang sangat sederhana atau bermasalah, memori mungkin tidak dapat digunakan hingga boot ulang. Tetapi jika Anda berada dalam situasi itu, Anda mungkin tidak akan menanyakan pertanyaan ini.
Sistem operasi mungkin membutuhkan waktu lama untuk membebaskan sumber daya tertentu. Misalnya port TCP yang digunakan server jaringan untuk menerima koneksi mungkin memerlukan beberapa menit untuk menjadi gratis, meskipun ditutup dengan benar oleh program. Program jaringan juga dapat menyimpan sumber daya jarak jauh seperti objek database. Sistem jarak jauh harus membebaskan sumber daya tersebut ketika koneksi jaringan terputus, tetapi mungkin memakan waktu lebih lama daripada sistem operasi lokal.
sumber
ipcrm
pembersihan manual, linux.die.net/man/8/ipcrm .Standar C tidak menentukan bahwa memori yang dialokasikan oleh
malloc
dilepaskan saat program berakhir. Ini dilakukan oleh sistem operasi dan tidak semua OS (biasanya ini berada di dunia tertanam) melepaskan memori saat program berakhir.sumber
main
mengembalikan semua memori yang dialokasikan olehmalloc
dilepaskan. Misalnya dikatakan bahwa semua file yang terbuka ditutup sebelum program dihentikan. Untuk memori yang dialokasikan sayamalloc
, itu hanya tidak ditentukan. Sekarang tentu saja kalimat saya tentang OS menjelaskan apa yang biasanya dilakukan bukan apa yang ditentukan Standar, karena tidak menentukan apa pun tentang ini.std::atexit
juga mempertimbangkan penghentian program melaluistd::exit
, dan kemudian ada jugastd::abort
dan (khusus C ++)std::terminate
.atexit
tidak akan bisa digunakan. :-)Karena semua jawaban telah mencakup sebagian besar aspek pertanyaan Anda tentang OS modern, tetapi secara historis, ada satu yang perlu disebutkan jika Anda pernah memprogram di dunia DOS. Terminant dan Stay Resident (TSR) biasanya akan mengembalikan kontrol ke sistem tetapi akan berada di memori yang dapat dihidupkan kembali oleh interupsi perangkat lunak / perangkat keras. Itu adalah hal yang normal untuk melihat pesan seperti "kehabisan memori! Coba bongkar beberapa TSR Anda" saat bekerja pada OS ini.
Jadi secara teknis program dihentikan , tetapi karena masih berada di memori, kebocoran memori apa pun tidak akan dilepaskan kecuali Anda membongkar program.
Jadi Anda dapat menganggap ini sebagai kasus lain selain OS yang tidak mengambil kembali memori baik karena bermasalah atau karena OS yang disematkan dirancang untuk melakukannya.
Saya ingat satu contoh lagi. Sistem Kontrol Informasi Pelanggan (CICS), server transaksi yang dijalankan terutama pada mainframe IBM bersifat pseudo-percakapan. Ketika dijalankan, itu memproses data yang dimasukkan pengguna, menghasilkan set data lain untuk pengguna, mentransfer ke node terminal pengguna dan berakhir. Saat mengaktifkan kunci perhatian, itu kembali untuk memproses kumpulan data lain. Karena cara perilakunya, secara teknis lagi, OS tidak akan mengambil kembali memori dari Program CICS yang dihentikan, kecuali Anda mendaur ulang server transaksi CICS.
sumber
Seperti yang dikatakan orang lain, sebagian besar sistem operasi akan mengklaim kembali memori yang dialokasikan setelah penghentian proses (dan mungkin sumber daya lain seperti soket jaringan, pegangan file, dll).
Karena itu, memori mungkin bukan satu-satunya hal yang perlu Anda khawatirkan saat berurusan dengan new / delete (bukan malloc mentah / gratis). Memori yang dialokasikan di new mungkin akan direklamasi, tetapi hal-hal yang mungkin dilakukan di destruktor objek tidak akan terjadi. Mungkin destruktor dari beberapa kelas menulis nilai sentinel ke dalam file setelah penghancuran. Jika proses berhenti begitu saja, pegangan file mungkin akan dihapus dan memori diambil kembali, tetapi nilai sentinel itu tidak akan ditulis.
Moral dari cerita, selalu bersihkan dirimu sendiri. Jangan biarkan hal-hal menjuntai. Jangan mengandalkan pembersihan OS setelah Anda. Bersihkan diri sendiri.
sumber
kill -9
kipas yang kurang terang muncul ...)std::exit
akan memanggil dokter,std::abort
tidak akan, pengecualian yang tidak tertangkap mungkin.Ini lebih cenderung bergantung pada sistem operasi daripada bahasa. Pada akhirnya program apa pun dalam bahasa apa pun akan mendapatkan memorinya dari sistem operasi.
Saya belum pernah mendengar sistem operasi yang tidak mendaur ulang memori saat program keluar / macet. Jadi, jika program Anda memiliki batas atas pada memori yang perlu dialokasikan, maka mengalokasikan dan tidak pernah membebaskan adalah hal yang wajar.
sumber
Jika program pernah berubah menjadi komponen dinamis ("plugin") yang dimuat ke dalam ruang alamat program lain, itu akan merepotkan, bahkan pada sistem operasi dengan manajemen memori yang rapi. Kami bahkan tidak perlu memikirkan tentang kode yang di-porting ke sistem yang kurang mampu.
Di sisi lain, melepaskan semua memori bisa memengaruhi kinerja pembersihan program.
Satu program yang sedang saya kerjakan, kasus uji tertentu memerlukan waktu 30 detik atau lebih untuk keluar dari program, karena program tersebut berulang melalui grafik semua memori dinamis dan melepaskannya sepotong demi sepotong.
Solusi yang masuk akal adalah memiliki kemampuan di sana dan menutupinya dengan kasus uji, tetapi mematikannya dalam kode produksi sehingga aplikasi berhenti dengan cepat.
sumber
Semua sistem operasi yang layak mendapatkan gelar tersebut akan membersihkan kekacauan yang dibuat oleh proses Anda setelah penghentian. Tetapi selalu ada kejadian yang tidak terduga, bagaimana jika aksesnya ditolak dan beberapa programmer yang buruk tidak meramalkan kemungkinan tersebut sehingga tidak mencoba lagi nanti? Selalu lebih aman untuk membersihkan diri Anda sendiri JIKA kebocoran memori adalah misi penting - jika tidak, upaya itu tidak sepadan dengan upaya IMO jika upaya itu mahal.
Sunting: Anda perlu membersihkan kebocoran memori jika berada di tempat yang akan menumpuk, seperti di loop. Kebocoran memori yang saya bicarakan adalah yang menumpuk dalam waktu konstan selama program berlangsung, jika Anda memiliki kebocoran jenis lain, kemungkinan besar akan menjadi masalah serius cepat atau lambat.
Dalam istilah teknis jika kebocoran Anda adalah 'kompleksitas' memori O (1) mereka baik-baik saja dalam banyak kasus, O (logn) sudah tidak menyenangkan (dan dalam beberapa kasus fatal) dan O (N) + tidak dapat ditoleransi.
sumber
Memori bersama pada sistem yang sesuai dengan POSIX tetap ada hingga shm_unlink dipanggil atau sistem di-boot ulang.
sumber
Jika Anda memiliki komunikasi antarproses, ini dapat menyebabkan proses lain tidak pernah menyelesaikan dan menghabiskan sumber daya bergantung pada protokolnya.
Sebagai contoh, saya pernah bereksperimen dengan mencetak ke printer PDF di Java ketika saya menghentikan JVM di tengah pekerjaan printer, proses spooling PDF tetap aktif, dan saya harus mematikannya di task manager sebelum saya bisa coba lagi mencetak.
sumber