Vous pouvez utiliser valgrind
pour le déboguer.
#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]$
Une solution possible :
#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]$
Consultez le blog sur l'utilisation de Valgrind Lien
8 votes
Je me demande pourquoi tout le monde suggère de
NULL
(ce qui masque des erreurs qui seraient autrement détectées, comme le montre bien cette question), mais personne ne suggère de ne pas faire de gestion manuelle de la mémoire du tout, ce qui est très bien possible en C++. Je n'ai pas écritdelete
en années. (Et, oui, mon code est critique en termes de performances. Sinon, il n'aurait pas été écrit en C++).2 votes
@sbi : La corruption de tas et autres sont rarement pris, du moins pas là où ils se produisent.
NULL
L'utilisation de pointeurs peut faire planter votre programme plus tôt.0 votes
@Hasturkun : Je ne suis pas du tout d'accord. Une incitation majeure à
NULL
est d'empêcher une deuxièmedelete ptr;
d'exploser - ce qui masque une erreur, parce que cette secondedelete
n'aurait jamais dû se produire. (Il est également utilisé pour vérifier si un pointeur pointe toujours vers un objet valide. Mais cela ne fait que soulever la question de savoir pourquoi vous avez un pointeur dans la portée qui n'a pas d'objet à pointer).1 votes
Je pense que toutes les réponses ci-dessous qui suggèrent de rechercher "manuellement" les problèmes de pointeurs et de les mettre à zéro, etc. sont de mauvais remèdes. Apprendre à utiliser l'un des vrais outils pour trouver ces problèmes est inestimable. Dans le cas de Valgrind, cela peut être aussi simple que d'installer apt-get valgrind et de préfixer votre programme avec valgrind et une option (comme le montre une des réponses ci-dessous).