Ketika saya menjalankan program (C ++) saya itu macet dengan kesalahan ini.
* glibc terdeteksi * ./load: bebas ganda atau rusak (! prev): 0x0000000000c6ed50 ***
Bagaimana cara melacak kesalahan tersebut?
Saya mencoba menggunakan std::cout
pernyataan print ( ), tidak berhasil. Bisakah gdb
membuat ini lebih mudah?
NULL
pointer (yang menutupi kesalahan yang jika tidak tertangkap, seperti yang ditunjukkan pertanyaan ini dengan baik), tetapi tidak ada yang menyarankan untuk tidak melakukan manajemen memori manual sama sekali, yang sangat mungkin dilakukan di C ++. Saya sudahdelete
bertahun-tahun tidak menulis . (Dan, ya, kode saya sangat penting untuk kinerja. Jika tidak, kode tidak akan ditulis dalam C ++.)NULL
petunjuk mungkin membuat program Anda crash lebih awal.NULL
petunjuk adalah untuk mencegah ledakan keduadelete ptr;
- yang menutupi kesalahan, karena detik itudelete
seharusnya tidak pernah terjadi. (Ini juga digunakan untuk memeriksa apakah sebuah pointer masih menunjuk ke objek yang valid. Tapi itu hanya menimbulkan pertanyaan mengapa Anda memiliki pointer dalam lingkup yang tidak memiliki objek untukJawaban:
Jika Anda menggunakan glibc, Anda dapat menyetel
MALLOC_CHECK_
variabel lingkungan ke2
, ini akan menyebabkan glibc menggunakan versi toleran kesalahanmalloc
, yang akan menyebabkan program Anda dibatalkan pada titik di mana free ganda selesai.Anda dapat mengatur ini dari gdb dengan menggunakan
set environment MALLOC_CHECK_ 2
perintah sebelum menjalankan program Anda; program harus dibatalkan, denganfree()
panggilan terlihat di backtrace.lihat halaman manual
malloc()
untuk informasi lebih lanjutsumber
MALLOC_CHECK_2
sebenarnya memperbaiki masalah bebas ganda saya (meskipun tidak memperbaiki jika hanya dalam mode debug)Setidaknya ada dua kemungkinan situasi:
Untuk yang pertama saya sangat menyarankan NULL-ing semua pointer yang dihapus.
Anda memiliki tiga opsi:
sumber
Anda dapat menggunakan gdb, tetapi saya akan mencoba Valgrind terlebih dahulu . Lihat panduan memulai cepat .
Singkatnya, Valgrind memperlengkapi program Anda sehingga dapat mendeteksi beberapa jenis kesalahan dalam menggunakan memori yang dialokasikan secara dinamis, seperti kebebasan ganda dan menulis melewati akhir blok memori yang dialokasikan (yang dapat merusak heap). Ini mendeteksi dan melaporkan kesalahan segera setelah terjadi , sehingga mengarahkan Anda langsung ke penyebab masalah.
sumber
Tiga aturan dasar:
NULL
setelah bebasNULL
sebelum membebaskan.NULL
awal.Kombinasi ketiganya bekerja dengan cukup baik.
sumber
Anda dapat menggunakan
valgrind
untuk men-debugnya.#include<stdio.h> #include<stdlib.h> int main() { char *x = malloc(100); free(x); free(x); return 0; } [sand@PS-CNTOS-64-S11 testbox]$ vim t1.c [sand@PS-CNTOS-64-S11 testbox]$ cc -g t1.c -o t1 [sand@PS-CNTOS-64-S11 testbox]$ ./t1 *** glibc detected *** ./t1: double free or corruption (top): 0x00000000058f7010 *** ======= Backtrace: ========= /lib64/libc.so.6[0x3a3127245f] /lib64/libc.so.6(cfree+0x4b)[0x3a312728bb] ./t1[0x400500] /lib64/libc.so.6(__libc_start_main+0xf4)[0x3a3121d994] ./t1[0x400429] ======= Memory map: ======== 00400000-00401000 r-xp 00000000 68:02 30246184 /home/sand/testbox/t1 00600000-00601000 rw-p 00000000 68:02 30246184 /home/sand/testbox/t1 058f7000-05918000 rw-p 058f7000 00:00 0 [heap] 3a30e00000-3a30e1c000 r-xp 00000000 68:03 5308733 /lib64/ld-2.5.so 3a3101b000-3a3101c000 r--p 0001b000 68:03 5308733 /lib64/ld-2.5.so 3a3101c000-3a3101d000 rw-p 0001c000 68:03 5308733 /lib64/ld-2.5.so 3a31200000-3a3134e000 r-xp 00000000 68:03 5310248 /lib64/libc-2.5.so 3a3134e000-3a3154e000 ---p 0014e000 68:03 5310248 /lib64/libc-2.5.so 3a3154e000-3a31552000 r--p 0014e000 68:03 5310248 /lib64/libc-2.5.so 3a31552000-3a31553000 rw-p 00152000 68:03 5310248 /lib64/libc-2.5.so 3a31553000-3a31558000 rw-p 3a31553000 00:00 0 3a41c00000-3a41c0d000 r-xp 00000000 68:03 5310264 /lib64/libgcc_s-4.1.2-20080825.so.1 3a41c0d000-3a41e0d000 ---p 0000d000 68:03 5310264 /lib64/libgcc_s-4.1.2-20080825.so.1 3a41e0d000-3a41e0e000 rw-p 0000d000 68:03 5310264 /lib64/libgcc_s-4.1.2-20080825.so.1 2b1912300000-2b1912302000 rw-p 2b1912300000 00:00 0 2b191231c000-2b191231d000 rw-p 2b191231c000 00:00 0 7ffffe214000-7ffffe229000 rw-p 7ffffffe9000 00:00 0 [stack] 7ffffe2b0000-7ffffe2b4000 r-xp 7ffffe2b0000 00:00 0 [vdso] ffffffffff600000-ffffffffffe00000 ---p 00000000 00:00 0 [vsyscall] Aborted [sand@PS-CNTOS-64-S11 testbox]$ [sand@PS-CNTOS-64-S11 testbox]$ vim t1.c [sand@PS-CNTOS-64-S11 testbox]$ cc -g t1.c -o t1 [sand@PS-CNTOS-64-S11 testbox]$ valgrind --tool=memcheck ./t1 ==20859== Memcheck, a memory error detector ==20859== Copyright (C) 2002-2009, and GNU GPL'd, by Julian Seward et al. ==20859== Using Valgrind-3.5.0 and LibVEX; rerun with -h for copyright info ==20859== Command: ./t1 ==20859== ==20859== Invalid free() / delete / delete[] ==20859== at 0x4A05A31: free (vg_replace_malloc.c:325) ==20859== by 0x4004FF: main (t1.c:8) ==20859== Address 0x4c26040 is 0 bytes inside a block of size 100 free'd ==20859== at 0x4A05A31: free (vg_replace_malloc.c:325) ==20859== by 0x4004F6: main (t1.c:7) ==20859== ==20859== ==20859== HEAP SUMMARY: ==20859== in use at exit: 0 bytes in 0 blocks ==20859== total heap usage: 1 allocs, 2 frees, 100 bytes allocated ==20859== ==20859== All heap blocks were freed -- no leaks are possible ==20859== ==20859== For counts of detected and suppressed errors, rerun with: -v ==20859== ERROR SUMMARY: 1 errors from 1 contexts (suppressed: 4 from 4) [sand@PS-CNTOS-64-S11 testbox]$ [sand@PS-CNTOS-64-S11 testbox]$ valgrind --tool=memcheck --leak-check=full ./t1 ==20899== Memcheck, a memory error detector ==20899== Copyright (C) 2002-2009, and GNU GPL'd, by Julian Seward et al. ==20899== Using Valgrind-3.5.0 and LibVEX; rerun with -h for copyright info ==20899== Command: ./t1 ==20899== ==20899== Invalid free() / delete / delete[] ==20899== at 0x4A05A31: free (vg_replace_malloc.c:325) ==20899== by 0x4004FF: main (t1.c:8) ==20899== Address 0x4c26040 is 0 bytes inside a block of size 100 free'd ==20899== at 0x4A05A31: free (vg_replace_malloc.c:325) ==20899== by 0x4004F6: main (t1.c:7) ==20899== ==20899== ==20899== HEAP SUMMARY: ==20899== in use at exit: 0 bytes in 0 blocks ==20899== total heap usage: 1 allocs, 2 frees, 100 bytes allocated ==20899== ==20899== All heap blocks were freed -- no leaks are possible ==20899== ==20899== For counts of detected and suppressed errors, rerun with: -v ==20899== ERROR SUMMARY: 1 errors from 1 contexts (suppressed: 4 from 4) [sand@PS-CNTOS-64-S11 testbox]$
Satu kemungkinan perbaikan:
#include<stdio.h> #include<stdlib.h> int main() { char *x = malloc(100); free(x); x=NULL; free(x); return 0; } [sand@PS-CNTOS-64-S11 testbox]$ vim t1.c [sand@PS-CNTOS-64-S11 testbox]$ cc -g t1.c -o t1 [sand@PS-CNTOS-64-S11 testbox]$ ./t1 [sand@PS-CNTOS-64-S11 testbox]$ [sand@PS-CNTOS-64-S11 testbox]$ valgrind --tool=memcheck --leak-check=full ./t1 ==20958== Memcheck, a memory error detector ==20958== Copyright (C) 2002-2009, and GNU GPL'd, by Julian Seward et al. ==20958== Using Valgrind-3.5.0 and LibVEX; rerun with -h for copyright info ==20958== Command: ./t1 ==20958== ==20958== ==20958== HEAP SUMMARY: ==20958== in use at exit: 0 bytes in 0 blocks ==20958== total heap usage: 1 allocs, 1 frees, 100 bytes allocated ==20958== ==20958== All heap blocks were freed -- no leaks are possible ==20958== ==20958== For counts of detected and suppressed errors, rerun with: -v ==20958== ERROR SUMMARY: 0 errors from 0 contexts (suppressed: 4 from 4) [sand@PS-CNTOS-64-S11 testbox]$
Lihat blog di menggunakan Valgrind Link
sumber
Dengan kompiler C ++ modern, Anda dapat menggunakan pembersih untuk melacak.
Contoh contoh:
Program saya:
$cat d_free.cxx #include<iostream> using namespace std; int main() { int * i = new int(); delete i; //i = NULL; delete i; }
Kompilasi dengan pembersih alamat:
# g++-7.1 d_free.cxx -Wall -Werror -fsanitize=address -g
Jalankan:
# ./a.out ================================================================= ==4836==ERROR: AddressSanitizer: attempting double-free on 0x602000000010 in thread T0: #0 0x7f35b2d7b3c8 in operator delete(void*, unsigned long) /media/sf_shared/gcc-7.1.0/libsanitizer/asan/asan_new_delete.cc:140 #1 0x400b2c in main /media/sf_shared/jkr/cpp/d_free/d_free.cxx:11 #2 0x7f35b2050c04 in __libc_start_main (/lib64/libc.so.6+0x21c04) #3 0x400a08 (/media/sf_shared/jkr/cpp/d_free/a.out+0x400a08) 0x602000000010 is located 0 bytes inside of 4-byte region [0x602000000010,0x602000000014) freed by thread T0 here: #0 0x7f35b2d7b3c8 in operator delete(void*, unsigned long) /media/sf_shared/gcc-7.1.0/libsanitizer/asan/asan_new_delete.cc:140 #1 0x400b1b in main /media/sf_shared/jkr/cpp/d_free/d_free.cxx:9 #2 0x7f35b2050c04 in __libc_start_main (/lib64/libc.so.6+0x21c04) previously allocated by thread T0 here: #0 0x7f35b2d7a040 in operator new(unsigned long) /media/sf_shared/gcc-7.1.0/libsanitizer/asan/asan_new_delete.cc:80 #1 0x400ac9 in main /media/sf_shared/jkr/cpp/d_free/d_free.cxx:8 #2 0x7f35b2050c04 in __libc_start_main (/lib64/libc.so.6+0x21c04) SUMMARY: AddressSanitizer: double-free /media/sf_shared/gcc-7.1.0/libsanitizer/asan/asan_new_delete.cc:140 in operator delete(void*, unsigned long) ==4836==ABORTING
Untuk mempelajari lebih lanjut tentang pembersih Anda dapat memeriksa ini atau ini atau semua kompiler c ++ modern (mis. Gcc, clang dll.) Dokumentasi.
sumber
Apakah Anda menggunakan petunjuk cerdas seperti Boost
shared_ptr
? Jika demikian, periksa apakah Anda langsung menggunakan pointer mentah di mana saja dengan memanggilget()
. Saya telah menemukan ini sebagai masalah yang cukup umum.Misalnya, bayangkan skenario di mana pointer mentah diteruskan (mungkin sebagai penangan panggilan balik, katakanlah) ke kode Anda. Anda mungkin memutuskan untuk menetapkan ini ke penunjuk cerdas untuk mengatasi penghitungan referensi dll. Kesalahan besar: kode Anda tidak memiliki penunjuk ini kecuali Anda mengambil salinan yang dalam. Ketika kode Anda selesai dengan penunjuk pintar, itu akan menghancurkannya dan mencoba untuk menghancurkan memori yang ditunjuknya karena ia berpikir bahwa tidak ada orang lain yang membutuhkannya, tetapi kode panggilan kemudian akan mencoba untuk menghapusnya dan Anda akan mendapatkan ganda masalah gratis.
Tentu saja, itu mungkin bukan masalah Anda di sini. Yang paling sederhana berikut ini adalah contoh yang menunjukkan bagaimana hal itu bisa terjadi. Penghapusan pertama baik-baik saja tetapi kompilator merasakan bahwa itu telah menghapus memori itu dan menyebabkan masalah. Itulah mengapa menetapkan 0 ke penunjuk segera setelah penghapusan adalah ide yang bagus.
int main(int argc, char* argv[]) { char* ptr = new char[20]; delete[] ptr; ptr = 0; // Comment me out and watch me crash and burn. delete[] ptr; }
Edit: diubah
delete
menjadidelete[]
, karena ptr adalah array dari char.sumber
Saya tahu ini adalah utas yang sangat lama, tetapi ini adalah pencarian google teratas untuk kesalahan ini, dan tidak ada tanggapan yang menyebutkan penyebab umum kesalahan tersebut.
Yang menutup file yang sudah Anda tutup.
Jika Anda tidak memperhatikan dan memiliki dua fungsi berbeda menutup file yang sama, maka yang kedua akan menghasilkan kesalahan ini.
sumber