Penjelasan terbaik yang pernah saya lihat adalah di Bab 7 dari Yayasan gratis e-book Pemrograman .
Pada dasarnya, di .NET kebocoran kehabisan memori terjadi ketika benda yang direferensikan telah di-root dan dengan demikian tidak dapat dikumpulkan dengan sampah. Ini terjadi secara tidak sengaja ketika Anda menyimpan referensi di luar ruang lingkup yang dimaksud.
Anda akan tahu bahwa Anda memiliki kebocoran ketika Anda mulai mendapatkan OutOfMemoryExceptions atau penggunaan memori Anda melampaui apa yang Anda harapkan ( PerfMon memiliki penghitung memori yang bagus).
Memahami model memori .NET adalah cara terbaik Anda untuk menghindarinya. Secara khusus, memahami cara kerja pengumpul sampah dan bagaimana referensi bekerja - lagi, saya merujuk Anda ke bab 7 dari e-book. Juga, waspadai perangkap umum, mungkin peristiwa yang paling umum. Jika objek A terdaftar untuk sebuah acara pada objek B , maka objek A akan bertahan sampai obyek B menghilang karena B memegang referensi ke A . Solusinya adalah dengan membatalkan registrasi acara Anda setelah selesai.
Tentu saja, profil memori yang baik akan memungkinkan Anda melihat grafik objek Anda dan menjelajahi nesting / referensi objek Anda untuk melihat dari mana referensi berasal dan objek root apa yang bertanggung jawab ( profil semut gerbang merah , JetBrains dotMemory, memprofiler benar-benar bagus pilihan, atau Anda dapat menggunakan WinDbg dan SOS hanya teks , tapi saya sangat merekomendasikan produk komersial / visual kecuali jika Anda seorang guru nyata).
Saya percaya kode yang tidak dikelola tunduk pada kebocoran memori yang khas, kecuali bahwa referensi bersama dikelola oleh pengumpul sampah. Saya bisa salah tentang poin terakhir ini.
Sebenarnya, kebocoran memori memakan memori yang "tidak lagi digunakan" oleh program.
"Tidak lagi digunakan" memiliki lebih dari satu makna, itu bisa berarti "tidak ada lagi referensi untuk itu", yaitu, benar-benar tidak dapat dipulihkan, atau itu bisa berarti, direferensikan, dipulihkan, tidak digunakan tetapi program tetap menyimpan referensi. Hanya nanti yang berlaku untuk .Net untuk objek yang dikelola dengan sempurna . Namun, tidak semua kelas sempurna dan pada titik tertentu implementasi yang tidak dikelola yang mendasari dapat membocorkan sumber daya secara permanen untuk proses itu.
Dalam semua kasus, aplikasi mengkonsumsi lebih banyak memori daripada yang dibutuhkan. Efek samping, tergantung pada jumlah yang bocor, bisa berubah dari tidak ada, ke pelambatan yang disebabkan oleh pengumpulan berlebihan, ke serangkaian pengecualian memori dan akhirnya kesalahan fatal diikuti oleh penghentian proses paksa.
Anda tahu aplikasi memiliki masalah memori saat pemantauan menunjukkan bahwa semakin banyak memori yang dialokasikan untuk proses Anda setelah setiap siklus pengumpulan sampah . Dalam kasus seperti itu, Anda menyimpan terlalu banyak memori, atau beberapa implementasi yang tidak dikelola yang mendasari bocor.
Untuk sebagian besar kebocoran, sumber daya dipulihkan saat proses dihentikan, namun beberapa sumber daya tidak selalu dipulihkan dalam beberapa kasus tertentu, pegangan kursor GDI terkenal karena hal itu. Tentu saja, jika Anda memiliki mekanisme komunikasi antarproses, memori yang dialokasikan dalam proses lain tidak akan dibebaskan sampai proses itu membebaskannya atau berakhir.
sumber
Saya pikir pertanyaan "apa itu kebocoran memori" dan "apa efeknya" telah dijawab dengan baik, tetapi saya ingin menambahkan beberapa hal lagi pada pertanyaan lain ...
Bagaimana memahami apakah aplikasi Anda bocor
Salah satu cara yang menarik adalah membuka perfmon dan menambahkan jejak # byte di semua tumpukan dan koleksi # Gen 2 , dalam setiap kasus hanya melihat proses Anda. Jika menjalankan fitur tertentu menyebabkan total byte meningkat, dan memori itu tetap dialokasikan setelah koleksi Gen 2 berikutnya, Anda mungkin mengatakan bahwa fitur tersebut membocorkan memori.
Bagaimana mencegahnya
Pendapat baik lainnya telah diberikan. Saya hanya akan menambahkan bahwa mungkin penyebab paling umum dari kebocoran memori .NET adalah untuk menambahkan event handler ke objek tanpa menghapusnya. Pengatur kejadian yang dilampirkan pada objek adalah bentuk referensi ke objek tersebut, sehingga akan mencegah pengumpulan bahkan setelah semua referensi lain telah hilang. Selalu ingat untuk melepaskan event handler (menggunakan
-=
sintaks dalam C #).Apakah kebocoran hilang ketika proses keluar, dan bagaimana dengan COM interop?
Ketika proses Anda keluar, semua memori yang dipetakan ke dalam ruang alamatnya diklaim kembali oleh OS, termasuk objek COM yang dilayani dari DLL. Relatif jarang, objek COM dapat dilayani dari proses yang terpisah. Dalam hal ini, ketika proses Anda keluar, Anda mungkin masih bertanggung jawab atas memori yang dialokasikan dalam setiap proses server COM yang Anda gunakan.
sumber
Saya akan mendefinisikan kebocoran memori sebagai objek yang tidak membebaskan semua memori yang dialokasikan setelah selesai. Saya telah menemukan ini dapat terjadi dalam aplikasi Anda jika Anda menggunakan Windows API dan COM (yaitu kode tidak dikelola yang memiliki bug di dalamnya atau tidak dikelola dengan benar), dalam kerangka kerja dan komponen pihak ketiga. Saya juga menemukan tidak beres setelah menggunakan benda-benda tertentu seperti pena dapat menyebabkan masalah.
Saya pribadi telah menderita Pengecualian Kehabisan Memori yang dapat disebabkan tetapi tidak eksklusif untuk kebocoran memori dalam aplikasi dot net. (OOM juga bisa berasal dari menjepit, lihat Pinning Artical ). Jika Anda tidak mendapatkan kesalahan OOM atau perlu mengkonfirmasi apakah ini merupakan kebocoran memori yang menyebabkannya, satu-satunya cara adalah dengan membuat profil aplikasi Anda.
Saya juga akan mencoba dan memastikan hal berikut:
a) Segala sesuatu yang menerapkan Idisposable dibuang baik menggunakan blok akhirnya atau pernyataan menggunakan ini termasuk kuas, pena dll (beberapa orang berpendapat untuk mengatur semuanya menjadi tidak ada tambahan)
b) Apa pun yang memiliki metode tutup ditutup lagi menggunakan akhirnya atau menggunakan pernyataan (meskipun saya telah menemukan menggunakan tidak selalu tutup tergantung jika Anda menyatakan objek di luar pernyataan menggunakan)
c) Jika Anda menggunakan kode / windows API yang tidak dikelola yang ditangani setelahnya dengan benar. (beberapa memiliki metode pembersihan untuk melepaskan sumber daya)
Semoga ini membantu.
sumber
Jika Anda perlu mendiagnosis kebocoran memori di .NET, periksa tautan ini:
http://msdn.microsoft.com/en-us/magazine/cc163833.aspx
http://msdn.microsoft.com/en-us/magazine/cc164138.aspx
Artikel-artikel tersebut menjelaskan cara membuat dump memori dari proses Anda dan bagaimana menganalisisnya sehingga Anda dapat menentukan terlebih dahulu apakah kebocoran Anda tidak dikelola atau dikelola, dan jika dikelola, bagaimana mencari tahu dari mana asalnya.
Microsoft juga memiliki alat yang lebih baru untuk membantu menghasilkan crash dumps, untuk menggantikan ADPlus, yang disebut DebugDiag.
http://www.microsoft.com/downloads/details.aspx?FamilyID=28bd5941-c458-46f1-b24d-f60151d875a3&displaylang=en
sumber
Menggunakan CLR Profiler dari Microsoft http://www.microsoft.com/downloads/details.aspx?familyid=86ce6052-d7f4-4aeb-9b7a-94635beebdda&displaylang=en adalah cara yang bagus untuk menentukan objek mana yang menahan memori, apa yang menyebabkan alur eksekusi, untuk penciptaan objek-objek ini, dan juga memonitor objek yang hidup di mana di tumpukan (fragmentasi, LOH, dll).
sumber
Penjelasan terbaik tentang cara kerja pemulung adalah di Jeff Richters CLR via C # book, (Bab 20). Membaca ini memberikan landasan yang bagus untuk memahami bagaimana objek bertahan.
Salah satu penyebab paling umum dari rooting objek secara tidak sengaja adalah dengan menghubungkan berbagai peristiwa di luar kelas. Jika Anda menghubungkan acara eksternal
misalnya
dan lupa melepaskan kaitannya ketika Anda membuang, maka SomeExternalClass memiliki referensi ke kelas Anda.
Seperti yang disebutkan di atas, profil memori SciTech sangat bagus untuk menunjukkan kepada Anda akar objek yang Anda curigai bocor.
Tetapi ada juga cara yang sangat cepat untuk memeriksa jenis tertentu hanya menggunakan WnDBG (Anda bahkan dapat menggunakan ini di jendela langsung VS.NET saat terpasang):
Sekarang lakukan sesuatu yang Anda pikir akan membuang objek jenis itu (mis. Tutup jendela). Berguna di sini untuk memiliki tombol debug di suatu tempat yang akan berjalan
System.GC.Collect()
beberapa kali.Kemudian jalankan
!dumpheap -stat -type <TypeName>
lagi. Jika jumlahnya tidak turun, atau tidak turun sebanyak yang Anda harapkan, maka Anda memiliki dasar untuk penyelidikan lebih lanjut. (Saya mendapat tip ini dari seminar yang diberikan oleh Ingo Rammer ).sumber
Saya kira dalam lingkungan yang terkelola, kebocoran adalah Anda menyimpan referensi yang tidak perlu ke sejumlah besar memori di sekitar.
sumber
Mengapa orang berpikir bahwa kebocoran memori di .NET tidak sama dengan kebocoran lainnya?
Kebocoran memori adalah ketika Anda melampirkan ke sumber daya dan jangan biarkan itu pergi. Anda dapat melakukan ini baik dalam kode terkelola dan tidak terkelola.
Mengenai .NET, dan alat pemrograman lain, ada ide tentang pengumpulan sampah, dan cara lain untuk meminimalkan situasi yang akan membuat aplikasi Anda bocor. Tetapi metode terbaik untuk mencegah kebocoran memori adalah Anda perlu memahami model memori yang mendasarinya, dan cara kerja berbagai hal, pada platform yang Anda gunakan.
Percaya bahwa GC dan sihir lain akan membersihkan kekacauan Anda adalah cara singkat untuk kebocoran memori, dan akan sulit ditemukan nanti.
Ketika coding tidak dikelola, Anda biasanya memastikan untuk membersihkan, Anda tahu bahwa sumber daya yang Anda pegang, akan menjadi tanggung jawab Anda untuk membersihkan, bukan milik petugas kebersihan.
Di NET. Di sisi lain, banyak orang berpikir bahwa GC akan membersihkan semuanya. Ya, memang ada gunanya bagi Anda, tetapi Anda perlu memastikan bahwa memang demikian. .NET membungkus banyak hal, jadi Anda tidak selalu tahu apakah Anda berhadapan dengan sumber daya yang dikelola atau tidak dikelola, dan Anda perlu memastikan apa yang Anda hadapi. Menangani font, sumber daya GDI, direktori aktif, basis data dll adalah hal-hal yang perlu Anda perhatikan.
Saya melihat banyak orang memiliki ini, dan saya sangat berharap ini akan berakhir. Anda tidak dapat meminta pengguna untuk menghentikan aplikasi Anda untuk membersihkan kekacauan Anda! Lihatlah browser, yang bisa berupa IE, FF dll, lalu buka, katakanlah, Google Reader, biarkan selama beberapa hari, dan lihat apa yang terjadi.
Jika Anda kemudian membuka tab lain di browser, berselancar ke beberapa situs, lalu tutup tab yang meng-host halaman lain yang membuat peramban bocor, apakah menurut Anda browser akan melepaskan memori? Tidak demikian halnya dengan IE. Di komputer saya, IE akan dengan mudah memakan memori 1 GiB dalam waktu singkat (sekitar 3-4 hari) jika saya menggunakan Google Reader. Beberapa surat kabar bahkan lebih buruk.
sumber
Benar. Juga, tidak menggunakan metode .dispose () pada objek sekali pakai yang sesuai dapat menyebabkan kebocoran mem. Cara termudah untuk melakukannya adalah dengan menggunakan blok karena secara otomatis mengeksekusi .Dispose () di akhir:
Dan jika Anda membuat kelas yang menggunakan objek yang tidak dikelola, jika Anda tidak menerapkan IDisposable dengan benar, Anda bisa menyebabkan kebocoran memori untuk pengguna kelas Anda.
sumber
Semua kebocoran memori diselesaikan dengan penghentian program.
Memori yang cukup bocor dan Sistem Operasi dapat memutuskan untuk menyelesaikan masalah atas nama Anda.
sumber
Saya akan setuju dengan Bernard tentang. Bersih apa kebocoran mem.
Anda dapat membuat profil aplikasi Anda untuk melihat penggunaan memorinya, dan menentukan bahwa jika mengelola banyak memori ketika seharusnya tidak, Anda bisa mengatakan itu memiliki kebocoran.
Dalam istilah yang dikelola saya akan meletakkan leher saya di telepon untuk mengatakan itu hilang begitu proses dibunuh / dihapus.
Kode yang tidak dikelola adalah binatang buasnya sendiri dan jika ada kebocoran di dalamnya, ia akan mengikuti kode standar. definisi kebocoran.
sumber
Juga perlu diingat bahwa .NET memiliki dua tumpukan, satu menjadi tumpukan objek besar. Saya percaya benda sekitar 85k atau lebih besar diletakkan di tumpukan ini. Tumpukan ini memiliki aturan seumur hidup yang berbeda dari tumpukan biasa.
Jika Anda membuat struktur memori yang besar (Kamus atau Daftar), akan lebih bijaksana untuk mencari apa aturan sebenarnya.
Sejauh reklamasi memori pada proses terminasi, kecuali jika Anda menjalankan Win98 atau yang setara, semuanya dilepaskan kembali ke OS pada terminasi. Satu-satunya pengecualian adalah hal-hal yang dibuka lintas proses dan proses lain masih memiliki sumber daya terbuka.
Objek COM bisa rumit tho. Jika Anda selalu menggunakan
IDispose
polanya, Anda akan aman. Tapi saya sudah menemukan beberapa majelis interop yang mengimplementasikanIDispose
. Kuncinya di sini adalah meneleponMarshal.ReleaseCOMObject
saat Anda selesai. Objek COM masih menggunakan penghitungan referensi COM standar.sumber
Saya menemukan Net Memory Profiler. Bantuan yang sangat baik ketika menemukan kebocoran memori di .Net. Ini tidak gratis seperti Microsoft CLR Profiler, tetapi lebih cepat dan lebih tepatnya menurut saya. SEBUAH
sumber
Satu definisi adalah: Tidak dapat melepaskan memori yang tidak terjangkau, yang tidak lagi dapat dialokasikan ke proses baru selama pelaksanaan proses alokasi. Sebagian besar dapat disembuhkan dengan menggunakan teknik GC atau dideteksi oleh alat otomatis.
Untuk informasi lebih lanjut, silakan kunjungi http://all-about-java-and-weblogic-server.blogspot.in/2014/01/what-is-memory-leak-in-java.html .
sumber