2009-07-15 7 views
5

Mein Programm ist so (main.c):Malloc, string Zeiger und 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); 
} 

und ich debuggen mit dem Werkzeug valgrind, hieß es, dass ($: valgrind --tool = memcheck --leak-check = full --track-origins = 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. 

Wer kann mir sagen, warum und wie es zu beheben.

Antwort

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

Sie die Größe von nur ‚erstes Mal‘ für einen String-Speicher zugewiesen wird.

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

Und dann versuchen Sie, ersten und zweiten darin zu passen. Das wird nie funktionieren. strcat erstellt nicht mehr Speicher, Sie müssen das in der malloc aufgenommen haben.

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

Es ist auch sizeof(char) zu tun, nicht notwendig, da, dass es ohnehin über die Art im Fall ändert es explict dort zu sein garantierte 1. Manche mögen sein haben, einige es Unordnung betrachten.

+1

es gibt keine Notwendigkeit, den Rückgabewert von 'malloc()' in C zu werfen; auch, 'sizeof (char)' ist immer '1' – Christoph

2

Sie reservieren nur genügend Platz für den ersten Platz in Seq.

1

seq ist nur (strlen (erste) +1) * sizeof (char) lang, nicht genug, um die verkettete Zeichenfolge zuerst + Sekunde zu halten.

-1

Ich konnte sehen, dass die Linie:

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

ist nicht falsch eingerahmt. Der Grund dafür ist, dass Sie eine String-Verkettung durchführen, bei der Sie keine richtige Quelle angeben. Es wird gut funktionieren, wenn Sie die obige Syntax in 2 Zeilen segregieren.

strcpy (seq, zuerst); strcat (seq, zweite);

Dies ist, weil, wenn Sie eine Zeichenfolge kopieren, wird es die Zeichenfolge von "zuerst" auf "Seq" kopieren. Nun, für die Verkettung von Strings, weil es die richtige Quelle nicht finden konnte [bedenke, dass du nicht ausdrücklich erwähnt hast, dass die Quelle "seq" ist], gibt es ein ungültiges Problem mit dem Schreibspeicherverlust.

Hoffe das klärt Ihre Frage. Bitte kehren Sie zurück, wenn weitere Informationen erforderlich sind.

+0

Auch, wie oben erwähnt, von anderen, müssen Sie den richtigen Speicher für seq zuweisen, um auch für" zweite "zu speichern. –

+0

'strcpy()' gibt sein erstes Argument zurück, also 'strcat (strcpy (seq, first), scond)' ist äquivalent zu 'strcpy (seq, fiest); strcat (seq, zweite); '. –

3

Wo ist die entsprechende free() für die malloc()?

+0

haha, ich habe es verloren, ich möchte nur den Fehler von strcpy und strcat demonstrieren. Natürlich sollte ich kostenlos hinzufügen (seq); Trotzdem danke. –

+0

Der Speicher wird implizit vom Betriebssystem freigegeben, nachdem 'main()' – Christoph

+1

zurückgibt. Wow - warum schreibe ich dann 'free()'?:-) – Justicle