2009-07-15 9 views
5

Mój program jest tak (main.c):Malloc, wskaźniki łańcuchowe i Valgrind

#include <stdlib.h> 
#include <stdio.h> 
void main(){ 
    char *first="hello "; 
    char *second="world!"; 
    char *seq=(char *)malloc((strlen(first)+1)*sizeof(char)); 
    strcat(strcpy(seq,first),second); 
    printf("%s\n",seq); 
    free(seq); 
} 

i debugować z valgrind narzędziowej, to powiedział, że ($: valgrind --tool = memcheck --leak-check = pełne --track-początki = yes ./main):

==5118== Memcheck, a memory error detector. 
==5118== Copyright (C) 2002-2008, and GNU GPL'd, by Julian Seward et al. 
==5118== Using LibVEX rev 1884, a library for dynamic binary translation. 
==5118== Copyright (C) 2004-2008, and GNU GPL'd, by OpenWorks LLP. 
==5118== Using valgrind-3.4.1, a dynamic binary instrumentation framework. 
==5118== Copyright (C) 2000-2008, and GNU GPL'd, by Julian Seward et al. 
==5118== For more details, rerun with: -v 
==5118== 
==5118== Invalid write of size 1 
==5118== at 0x402575B: strcat (in /usr/lib/valgrind/x86-linux/vgpreload_memcheck.so) 
==5118== by 0x80484EB: main (main.c:7) 
==5118== Address 0x418a02f is 0 bytes after a block of size 7 alloc'd 
==5118== at 0x402522D: malloc (in /usr/lib/valgrind/x86-linux/vgpreload_memcheck.so) 
==5118== by 0x80484C3: main (main.c:6) 
==5118== 
==5118== Invalid write of size 1 
==5118== at 0x4025777: strcat (in /usr/lib/valgrind/x86-linux/vgpreload_memcheck.so) 
==5118== by 0x80484EB: main (main.c:7) 
==5118== Address 0x418a034 is 5 bytes after a block of size 7 alloc'd 
==5118== at 0x402522D: malloc (in /usr/lib/valgrind/x86-linux/vgpreload_memcheck.so) 
==5118== by 0x80484C3: main (main.c:6) 
==5118== 
==5118== Invalid read of size 1 
==5118== at 0x4025963: strlen (in /usr/lib/valgrind/x86-linux/vgpreload_memcheck.so) 
==5118== by 0x40A0FA4: puts (in /lib/libc-2.10.1.so) 
==5118== by 0x80484F7: main (main.c:8) 
==5118== Address 0x418a02f is 0 bytes after a block of size 7 alloc'd 
==5118== at 0x402522D: malloc (in /usr/lib/valgrind/x86-linux/vgpreload_memcheck.so) 
==5118== by 0x80484C3: main (main.c:6) 
==5118== 
==5118== Invalid read of size 1 
==5118== at 0x40ACEFE: _IO_default_xsputn (in /lib/libc-2.10.1.so) 
==5118== by 0x40AA3D0: [email protected]@GLIBC_2.1 (in /lib/libc-2.10.1.so) 
==5118== by 0x40A1020: puts (in /lib/libc-2.10.1.so) 
==5118== by 0x80484F7: main (main.c:8) 
==5118== Address 0x418a02f is 0 bytes after a block of size 7 alloc'd 
==5118== at 0x402522D: malloc (in /usr/lib/valgrind/x86-linux/vgpreload_memcheck.so) 
==5118== by 0x80484C3: main (main.c:6) 
hello world! 
==5118== 
==5118== ERROR SUMMARY: 17 errors from 4 contexts (suppressed: 13 from 1) 
==5118== malloc/free: in use at exit: 7 bytes in 1 blocks. 
==5118== malloc/free: 1 allocs, 0 frees, 7 bytes allocated. 
==5118== For counts of detected errors, rerun with: -v 
==5118== searching for pointers to 1 not-freed blocks. 
==5118== checked 47,492 bytes. 
==5118== 
==5118== 
==5118== 7 bytes in 1 blocks are definitely lost in loss record 1 of 1 
==5118== at 0x402522D: malloc (in /usr/lib/valgrind/x86-linux/vgpreload_memcheck.so) 
==5118== by 0x80484C3: main (main.c:6) 
==5118== 
==5118== LEAK SUMMARY: 
==5118== definitely lost: 7 bytes in 1 blocks. 
==5118==  possibly lost: 0 bytes in 0 blocks. 
==5118== still reachable: 0 bytes in 0 blocks. 
==5118==   suppressed: 0 bytes in 0 blocks. 

Kto może mi powiedzieć, dlaczego i jak to naprawić.

Odpowiedz

17
char *seq=(char *)malloc((strlen(first)+1)*sizeof(char)); 

Przydzielasz pamięć na ciąg o rozmiarze "pierwszym".

strcat(strcpy(seq,first),second); 

A potem próbujesz dopasować zarówno pierwszy, jak i drugi. To nigdy nie zadziała. strcat nie tworzy więcej pamięci, musisz to uwzględnić w malloc.

There is no need to cast the result of malloc in pure C.

Nie jest również konieczne, aby zrobić sizeof(char), jako że jest gwarancją 1. Niektórzy lubią mieć go mimo to być explict o typie w przypadku zmiany, niektórzy uważają, że bałagan.

+1

nie ma potrzeby rzutowania wartości zwracanej przez 'malloc()' w C; także, 'sizeof (char)' jest zawsze '1' – Christoph

2

Przydzielasz tylko tyle miejsca na pierwsze w seq.

1

seq jest tylko (strlen (pierwszy) +1) * sizeof (char) długi, niewystarczający, aby utrzymać połączony ciąg pierwszy + drugi.

-1

mogę zobaczyć, że linia:

strcat (StrCpy (seq wcześniej), s);

nie jest nieprawidłowo oprawione. Powodem jest to, że robisz ciąg konkatenacji, gdzie nie podajesz właściwego źródła. Będzie działało dobrze, jeśli podzielisz powyższą składnię na 2 linie.

strcpy (seq, pierwszy); strcat (seq, second);

Dzieje się tak dlatego, że podczas kopiowania ciągów będzie on kopiował ciąg od "first" do "seq". Teraz do łączenia ciągów, ponieważ nie może znaleźć właściwego źródła [pamiętaj, że nie wspomniałeś konkretnie, że źródłem jest "seq"], daje on nieprawidłowy problem z wyciekiem pamięci zapisu.

Mam nadzieję, że to wyjaśnia twoje pytanie. Proszę, jeśli chcesz uzyskać więcej informacji, proszę, cofnij się.

+0

Ponadto, jak wspomniano powyżej, przez innych, trzeba przydzielić odpowiednią pamięć dla seq, do przechowywania dla" sekund "również. –

+0

'strcpy()' zwraca pierwszy argument, więc 'strcat (strcpy (seq, first), scond)' jest równoważne 'strcpy (seq, fiest); strcat (seq, second); '. –

3

Gdzie jest odpowiednia free() dla malloc()?

+0

haha, zgubiłem go, chcę tylko zademonstrować błąd strcpy i strcat. Oczywiście powinienem dodać za darmo (seq); dziękuję ci wszystkim. –

+0

pamięć jest domyślnie wolna od systemu operacyjnego po 'main()' zwraca – Christoph

+1

Wow - dlaczego kiedykolwiek zawracam sobie głowę wywołaniem 'free()'?:-) – Justicle