How to track down a “double free or corruption” error
当我运行(C ++)程序时,它因该错误而崩溃。
* glibc detected * ./load: double free or corruption (!prev):
0x0000000000c6ed50 ***
如何跟踪错误?
我尝试使用print(
如果您使用的是glibc,则可以将
您可以在运行程序之前使用
有关更多信息,请参见
至少有两种可能的情况:
对于第一个,我强烈建议对所有已删除的指针进行NULL处理。
您有三种选择:
您可以使用gdb,但我会先尝试Valgrind。请参阅快速入门指南。
简要地说,Valgrind对您的程序进行了检测,以便它可以在使用动态分配的内存时检测几种错误,例如,两次释放并在分配的内存块末尾进行写操作(这可能会破坏堆)。它会立即检测并报告错误,从而使您直接找到问题的原因。
三个基本规则:
这三者的结合效果很好。
您可以使用
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 | #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]$ |
一种可能的解决方法:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 | #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]$ |
查看有关使用Valgrind Link的博客
使用现代C ++编译器,您可以使用消毒剂进行跟踪。
示例示例:
我的程序:
1 2 3 4 5 6 7 8 9 10 11 12 13 | $cat d_free.cxx #include<iostream> using namespace std; int main() { int * i = new int(); delete i; //i = NULL; delete i; } |
用地址清理器进行编译:
1 | # g++-7.1 d_free.cxx -Wall -Werror -fsanitize=address -g |
执行 :
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 | # ./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 |
要了解有关消毒剂的更多信息,可以查看此文档或此文档或任何现代c ++编译器(例如gcc,clang等)文档。
您是否正在使用诸如Boost
例如,设想一个场景,其中将原始指针(例如,作为回调处理程序)传递给了代码。您可能决定将其分配给智能指针,以应对引用计数等问题。大错误:除非进行深拷贝,否则代码不拥有此指针。当您的代码使用智能指针完成后,它将销毁它并尝试销毁它指向的内存,因为它认为没有其他人需要它,但是调用代码随后将尝试删除它,并且您会得到两倍免费的问题。
当然,这可能不是您的问题。最简单的是,下面的示例说明了它如何发生。第一次删除是可以的,但是编译器会感觉到它已经删除了该内存并导致了问题。因此,删除后立即为指针分配0是一个好主意。
1 2 3 4 5 6 7 8 | 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; } |
编辑:将
我知道这是一个非常老的线程,但这是Google对该错误的最高搜索,并且没有响应提及该错误的常见原因。
这将关闭您已经关闭的文件。
如果您不注意并且有两个不同的函数关闭同一个文件,则第二个将生成此错误。