Dalam kode C / C ++ yang tidak dikelola, praktik apa yang terbaik untuk mendeteksi kebocoran memori? Dan pedoman pengkodean yang harus dihindari? (Seolah itu sesederhana itu;)
Kami telah menggunakan sedikit cara konyol di masa lalu: memiliki peningkatan penghitung untuk setiap panggilan alokasi dan pengurangan memori saat membebaskan. Pada akhir program, nilai penghitung harus nol.
Saya tahu ini bukan cara yang bagus dan ada beberapa tangkapan. (Misalnya, jika Anda membebaskan memori yang dialokasikan oleh panggilan platform API, jumlah alokasi Anda tidak akan sama persis dengan jumlah membebaskan Anda. Tentu saja, maka kami menambah penghitung saat memanggil panggilan API yang mengalokasikan memori.)
Saya mengharapkan pengalaman, saran, dan mungkin beberapa referensi untuk alat yang menyederhanakan ini.
sumber
Jawaban:
Jika kode C / C ++ Anda portabel untuk * nix, beberapa hal lebih baik daripada Valgrind .
sumber
Jika Anda menggunakan Visual Studio, Microsoft menyediakan beberapa fungsi yang berguna untuk mendeteksi dan men-debug kebocoran memori.
Saya akan mulai dengan artikel ini: https://msdn.microsoft.com/en-us/library/x98tx3cf(v=vs.140).aspx
Berikut ringkasan artikel-artikel tersebut. Pertama, sertakan tajuk ini:
Maka Anda perlu memanggil ini ketika program Anda keluar:
Atau, jika program Anda tidak keluar di tempat yang sama setiap kali, Anda dapat memanggil ini di awal program Anda:
Sekarang ketika program keluar dari semua alokasi yang tidak gratis akan dicetak di Window Output bersama dengan file mereka dialokasikan dan terjadi alokasi.
Strategi ini berfungsi untuk sebagian besar program. Namun, menjadi sulit atau tidak mungkin dalam kasus-kasus tertentu. Menggunakan pustaka pihak ketiga yang melakukan beberapa inisialisasi saat startup dapat menyebabkan objek lain muncul di memori dump dan dapat membuat melacak kebocoran Anda sulit. Juga, jika ada kelas Anda memiliki anggota dengan nama yang sama dengan rutin alokasi memori (seperti malloc), makro debug CRT akan menyebabkan masalah.
Ada teknik lain yang dijelaskan dalam tautan MSDN yang dirujuk di atas yang dapat digunakan juga.
sumber
Di C ++: gunakan RAII. Smart pointer seperti
std::unique_ptr
,std::shared_ptr
,std::weak_ptr
adalah teman Anda.sumber
Sebagai Pengembang C ++ inilah beberapa pedoman sederhana:
Sedangkan untuk mendeteksi kebocoran memori secara pribadi, saya selalu menggunakan Visual Leak Detector dan merasa sangat berguna.
sumber
Saya telah menggunakan DevStudio selama bertahun-tahun sekarang dan selalu membuat saya kagum betapa banyak programmer tidak tahu tentang alat analisis memori yang tersedia di pustaka run time debug. Berikut beberapa tautan untuk memulai:
Melacak Heap Allocation Requests - khususnya bagian tentang Nomor Permintaan Alokasi Unik
_CrtSetDbgFlag
_CrtSetBreakAlloc
Tentu saja, jika Anda tidak menggunakan DevStudio maka ini tidak akan sangat membantu.
sumber
Saya kagum tidak ada yang menyebutkan DebugDiag untuk OS Windows.
Ini berfungsi pada rilis rilis, dan bahkan di lokasi pelanggan.
(Anda hanya perlu menyimpan PDB versi rilis, dan mengonfigurasi DebugDiag untuk menggunakan server simbol publik Microsoft)
sumber
Detektor Kebocoran Visual adalah alat yang sangat bagus, meskipun tidak mendukung panggilan pada runtime VC9 (misalnya MSVCR90D.DLL).
sumber
Microsoft VC ++ dalam mode debug menunjukkan kebocoran memori, meskipun tidak menunjukkan di mana kebocoran Anda.
Jika Anda menggunakan C ++ Anda selalu dapat menghindari menggunakan baru secara eksplisit: Anda memiliki
vector
,string
,auto_ptr
(pra C ++ 11; digantikan olehunique_ptr
C ++ 11),unique_ptr
(C ++ 11) danshared_ptr
(C ++ 11) di gudang Anda.Ketika hal baru tidak dapat dihindari, coba sembunyikan di konstruktor (dan sembunyikan hapus di destruktor); karya yang sama untuk API pihak ke-3.
sumber
Ada berbagai pustaka "malloc" pengganti di luar sana yang akan memungkinkan Anda untuk memanggil fungsi di bagian akhir dan itu akan memberi tahu Anda tentang semua memori yang belum diolah, dan dalam banyak kasus, siapa yang malloced (atau yang baru) di tempat pertama .
sumber
Jika Anda menggunakan MS VC ++, saya sangat merekomendasikan alat gratis ini dari codeproject : leakfinder oleh Jochen Kalmbach.
Anda cukup menambahkan kelas ke proyek Anda, dan menelepon
sebelum dan sesudah kode Anda ingin memeriksa kebocoran.
Setelah Anda membuat dan menjalankan kode, Jochen menyediakan alat GUI yang rapi di mana Anda dapat memuat file .xmlleaks yang dihasilkan, dan menavigasi melalui tumpukan panggilan di mana setiap kebocoran dihasilkan untuk memburu garis kode yang menyinggung.
PurifyPlus dari Rasional (sekarang dimiliki oleh IBM) mengilustrasikan kebocoran dengan cara yang serupa, tetapi saya menemukan alat leakfinder sebenarnya lebih mudah digunakan, dengan bonus itu tidak menelan biaya beberapa ribu dolar!
sumber
Tidak pernah menggunakannya sendiri, tetapi teman C saya memberi tahu saya Purify .
sumber
Jika Anda menggunakan Visual Studio, mungkin layak melihat Bounds Checker . Ini tidak gratis, tetapi sudah sangat membantu dalam menemukan kebocoran dalam kode saya. Tidak hanya kebocoran memori, tetapi juga kebocoran sumber daya GDI, kesalahan penggunaan WinAPI, dan hal-hal lainnya. Itu bahkan akan menunjukkan kepada Anda di mana memori bocor diinisialisasi, sehingga lebih mudah untuk melacak kebocoran.
sumber
Saya pikir tidak ada jawaban mudah untuk pertanyaan ini. Bagaimana Anda benar-benar mendekati solusi ini tergantung pada kebutuhan Anda. Apakah Anda memerlukan solusi lintas platform? Apakah Anda menggunakan baru / hapus atau malloc / gratis (atau keduanya)? Apakah Anda benar-benar mencari hanya "kebocoran" atau apakah Anda menginginkan perlindungan yang lebih baik, seperti mendeteksi buffer overruns (atau underruns)?
Jika Anda bekerja di sisi windows, pustaka runtime MS debug memiliki beberapa fungsi pendeteksian debug dasar, dan seperti yang lain telah ditunjukkan, ada beberapa pembungkus yang dapat disertakan dalam sumber Anda untuk membantu dengan deteksi kebocoran. Menemukan paket yang dapat bekerja dengan baik baru / delete dan malloc / gratis jelas memberi Anda lebih banyak fleksibilitas.
Saya tidak cukup tahu tentang sisi unix untuk memberikan bantuan, meskipun sekali lagi, yang lain sudah.
Tapi selain deteksi kebocoran, ada gagasan mendeteksi korupsi memori melalui buffer overruns (atau underruns). Jenis fungsi debug ini menurut saya lebih sulit daripada deteksi kebocoran biasa. Jenis sistem ini juga lebih rumit jika Anda bekerja dengan objek C ++ karena kelas polimorfik dapat dihapus dengan berbagai cara yang menyebabkan kesulitan dalam menentukan pointer basis sebenarnya yang sedang dihapus. Saya tahu tidak ada sistem "bebas" yang baik yang melakukan perlindungan yang layak untuk overruns. kami telah menulis sebuah sistem (lintas platform) dan ternyata cukup menantang.
sumber
Saya ingin menawarkan sesuatu yang pernah saya gunakan di masa lalu: pemeriksa kebocoran dasar yang tingkat sumber dan cukup otomatis. Saya memberikan ini karena tiga alasan:
Anda mungkin menemukan itu berguna.
Meskipun ini agak krufty, aku tidak membiarkan itu membuatku malu.
Meskipun itu terkait dengan beberapa kait win32, itu seharusnya mudah diatasi.
Ada beberapa hal yang Anda harus berhati-hati ketika menggunakannya: jangan melakukan apa pun yang perlu bersandar pada
new
kode yang mendasarinya, waspadalah terhadap peringatan tentang kasus yang mungkin terlewat di bagian atas leakcheck.cpp, sadarilah bahwa jika Anda menghidupkan pada (dan memperbaiki masalah apa pun dengan) kode yang melakukan dump gambar, Anda dapat menghasilkan file besar.Desain ini dimaksudkan untuk memungkinkan Anda menghidupkan dan mematikan checker tanpa mengkompilasi ulang semua yang menyertakan headernya. Sertakan leakcheck.h di mana Anda ingin melacak pengecekan dan membangun kembali satu kali. Setelah itu, kompilasi leakcheck.cpp dengan atau tanpa LEAKCHECK # define'd lalu relink untuk menghidupkan dan mematikannya. Termasuk unleakcheck.h akan mematikannya secara lokal di file. Dua makro disediakan: CLEARALLOCINFO () akan menghindari melaporkan file dan baris yang sama secara tidak tepat ketika Anda melintasi kode alokasi yang tidak termasuk leakcheck.h. ALLOCFENCE () hanya menghapus satu baris dalam laporan yang dihasilkan tanpa melakukan alokasi apa pun.
Sekali lagi, tolong sadari bahwa saya belum pernah menggunakan ini dalam beberapa saat dan Anda mungkin harus bekerja sedikit dengannya. Saya menjatuhkannya untuk menggambarkan ide itu. Jika ternyata ada minat yang cukup, saya bersedia mengerjakan contoh, memperbarui kode dalam proses, dan mengganti konten URL berikut dengan sesuatu yang lebih bagus yang mencakup daftar berwarna sintaksis.
Anda dapat menemukannya di sini: http://www.cse.ucsd.edu/~tkammeye/leakcheck.html
sumber
Untuk Linux: Coba Google Perftools
Ada banyak alat yang melakukan alokasi / penghitungan gratis yang serupa, kelebihan dari Goolge Perftools:
sumber
Pertahanan terbaik terhadap kebocoran adalah struktur program yang meminimalkan penggunaan malloc. Ini tidak hanya baik dari perspektif pemrograman, tetapi juga meningkatkan kinerja dan pemeliharaan. Saya tidak berbicara tentang menggunakan hal-hal lain sebagai ganti malloc, tetapi dalam hal menggunakan kembali objek dan menjaga tab yang sangat eksplisit pada semua objek yang dilewatkan daripada mengalokasikan secara sembarangan seperti yang sering digunakan dalam bahasa dengan pengumpul sampah seperti Jawa.
Misalnya, program yang saya kerjakan memiliki banyak objek bingkai yang mewakili data gambar. Setiap objek frame memiliki sub-data, yang membebaskan frame destructor. Program menyimpan daftar semua frame yang dialokasikan, dan ketika itu membutuhkan yang baru, memeriksa daftar objek frame yang tidak digunakan untuk melihat apakah ia dapat menggunakan kembali yang sudah ada daripada mengalokasikan yang baru. Pada shutdown, itu hanya berulang melalui daftar, membebaskan semuanya.
sumber
Saya akan merekomendasikan menggunakan Memory Validator dari verifikasi perangkat lunak. Alat ini terbukti merupakan bantuan yang tak ternilai untuk membantu saya melacak kebocoran memori dan meningkatkan manajemen memori aplikasi yang sedang saya kerjakan.
Alat yang sangat lengkap dan cepat.
sumber
Apakah Anda menghitung allocs dan membebaskan dengan interpolasi fungsi syscall Anda sendiri yang merekam panggilan dan kemudian meneruskan panggilan ke fungsi yang sebenarnya?
Ini adalah satu-satunya cara Anda dapat melacak panggilan yang berasal dari kode yang belum Anda tulis.
Lihatlah halaman manual untuk ld.so. Atau ld.so.1 pada beberapa sistem.
Juga lakukan Google LD_PRELOAD dan Anda akan menemukan beberapa artikel menarik yang menjelaskan teknik ini di www.itworld.com.
sumber
Setidaknya untuk MS VC ++, pustaka C Runtime memiliki beberapa fungsi yang saya temukan sangat membantu di masa lalu. Periksa bantuan MSDN untuk
_Crt*
fungsinya.sumber
Mmgr Paul Nettle adalah alat favorit saya sejak lama. Anda menyertakan mmgr.h dalam file sumber Anda, menentukan TEST_MEMORY, dan memberikan file teks penuh masalah memori yang terjadi selama menjalankan aplikasi Anda.
sumber
Pedoman Pengodean Umum:
sumber
Alat debugging memori bernilai emas, tetapi selama bertahun-tahun saya telah menemukan bahwa dua ide sederhana dapat digunakan untuk mencegah sebagian besar kebocoran memori / sumber daya dikodekan.
Tulis kode rilis segera setelah menulis kode akuisisi untuk sumber daya yang ingin Anda alokasikan. Dengan metode ini lebih sulit untuk "dilupakan" dan dalam beberapa hal memaksa seseorang untuk secara serius memikirkan siklus sumber daya yang digunakan di muka alih-alih sebagai tambahan.
Gunakan pengembalian sesedikit mungkin. Apa yang dialokasikan seharusnya hanya dibebaskan di satu tempat jika memungkinkan. Jalur bersyarat antara perolehan sumber daya dan pelepasan harus dirancang sesederhana dan sejelas mungkin.
sumber
Di bagian atas daftar ini (ketika saya membacanya) adalah valgrind. Valgrind sangat baik jika Anda dapat mereproduksi kebocoran pada sistem pengujian. Saya telah menggunakannya dengan sukses besar.
Bagaimana jika Anda baru saja memperhatikan bahwa sistem produksinya bocor sekarang dan Anda tidak tahu bagaimana cara mereproduksinya dalam pengujian? Beberapa bukti tentang apa yang salah ditangkap dalam keadaan sistem produksi itu, dan mungkin cukup untuk memberikan wawasan tentang di mana masalahnya sehingga Anda dapat memperbanyaknya.
Di situlah pengambilan sampel Monte Carlo. Baca artikel blog Raymond Chen, "Cara orang miskin mengidentifikasi kebocoran memori" dan kemudian periksa implementasi saya (menganggap Linux, hanya diuji pada x86 dan x86-64)
http://github.com/tialaramex/leakdice/tree/master
sumber
Bekerja pada sistem operasi ponsel Motorola, kami membajak perpustakaan alokasi memori untuk mengamati semua alokasi memori. Ini membantu untuk menemukan banyak masalah dengan alokasi memori. Karena pencegahan lebih baik daripada mengobati, saya akan merekomendasikan untuk menggunakan alat analisis statis seperti Klockwork atau PC-Lint
sumber
lint
. Ini memiliki banyak pemeriksaan khusus untuk C ++, yang afaik belat tidak. Lihat tautan dalam jawaban (yang saya beri nama baru dari Lint ke PC-Lint).Valgrind adalah opsi yang bagus untuk Linux. Di bawah MacOS X, Anda dapat mengaktifkan pustaka MallocDebug yang memiliki beberapa opsi untuk men-debug masalah alokasi memori (lihat manual malloc, bagian "LINGKUNGAN" memiliki detail yang relevan). OS X SDK juga menyertakan alat yang disebut MallocDebug (biasanya dipasang di / Developer / Applications / Performance Tools /) yang dapat membantu Anda memantau penggunaan dan kebocoran.
sumber
Deteksi:
Debug CRT
Menghindari:
Pointer pintar, boehm GC
sumber
Pengganti malloc, calloc, dan reallloc yang bagus adalah rmdebug, cukup mudah digunakan. Jauh lebih cepat untuk melakukan valgrind, sehingga Anda dapat menguji kode Anda secara luas. Tentu saja ada beberapa kerugian, begitu Anda menemukan kebocoran, Anda mungkin masih perlu menggunakan valgrind untuk menemukan di mana kebocoran itu muncul dan Anda hanya dapat menguji mallocs yang Anda lakukan secara langsung. Jika lib bocor karena Anda salah menggunakannya, rmdebug tidak akan menemukannya.
http://www.hexco.de/rmdebug/
sumber
Sebagian besar memori profiler memperlambat aplikasi Windows kompleks saya yang besar ke titik di mana hasilnya tidak berguna. Ada satu alat yang berfungsi dengan baik untuk menemukan kebocoran di aplikasi saya: UMDH - http://msdn.microsoft.com/en-us/library/ff560206%28VS.85%29.aspx
sumber
Mtrace tampaknya menjadi standar bawaan untuk linux. Langkah-langkahnya adalah:
MALLOC_TRACE = / tmp / mtrace.dat
ekspor MALLOC_TRACE;
mtrace your_prog_exe_name /tmp/mtrace.dat
(saya harus menginstal skrip perl mtrace terlebih dahulu pada sistem fedora saya dengan yum install glibc_utils )
sumber