2009-07-15 36 views
5

chương trình của tôi là như thế này (main.c):Malloc, con trỏ chuỗi, và 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); 
} 

và tôi gỡ lỗi với valgrind công cụ, nó nói rằng ($: valgrind --tool = memcheck --leak-check = full --track-origins = có ./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. 

Ai có thể cho tôi biết lý do và cách khắc phục.

Trả lời

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

Bạn đang cấp phát bộ nhớ cho chuỗi có kích thước chỉ là 'đầu tiên'.

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

Và sau đó bạn cố gắng vừa với cả đầu tiên và thứ hai trong đó. Điều đó sẽ không bao giờ hoạt động. strcat không tạo thêm bộ nhớ, bạn cần phải bao gồm trong số malloc.

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

Nó cũng không phải là cần thiết để làm sizeof(char), vì đó là đảm bảo được 1. Một số muốn có nó ở đó anyway để được explict về loại trong trường hợp nó thay đổi, một số xem xét nó lộn xộn.

+1

không cần phải bỏ giá trị trả lại của 'malloc()' vào C; Ngoài ra, 'sizeof (char)' luôn luôn là '1' – Christoph

2

Bạn chỉ phân bổ đủ dung lượng cho lần đầu tiên trong seq.

1

seq chỉ (strlen (đầu tiên) +1) * sizeof (char) dài, không đủ để giữ chuỗi được nối đầu tiên + giây.

-1

Tôi có thể thấy rằng dòng:

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

không được đóng khung sai. Lý do là, bạn đang làm một chuỗi nối, nơi bạn không đưa ra một nguồn thích hợp. Nó sẽ hoạt động tốt, nếu bạn phân tách cú pháp trên thành 2 dòng.

strcpy (seq, trước tiên); strcat (seq, giây);

Điều này là do, khi bạn đang làm một bản sao chuỗi, nó sẽ sao chép chuỗi từ "đầu tiên" sang "seq". Bây giờ, đối với chuỗi nối, vì nó không thể tìm thấy nguồn thích hợp [nhớ rằng bạn đã không đề cập cụ thể rằng nguồn là "seq"], nó đưa ra một vấn đề rò rỉ bộ nhớ ghi không hợp lệ.

Hy vọng điều này sẽ làm rõ câu hỏi của bạn. Vui lòng hoàn nguyên, nếu cần thêm thông tin, cho cùng một.

+0

Ngoài ra, như đã đề cập ở trên, bởi những người khác, bạn cần phải cấp phát bộ nhớ thích hợp cho seq, để lưu trữ cho" thứ hai "cũng. –

+0

'strcpy()' trả về đối số đầu tiên của nó, vì vậy 'strcat (strcpy (seq, first), scond)' tương đương với 'strcpy (seq, fiest); strcat (seq, second); '. –

3

Trường hợp tương ứng free() cho số malloc()?

+0

haha, tôi mất nó, tôi chỉ muốn chứng minh lỗi của strcpy và strcat. Tất nhiên, tôi nên thêm miễn phí (seq); cảm ơn tất cả các bạn. –

+0

bộ nhớ là hoàn toàn free'd bởi hệ điều hành sau khi 'main()' trả về – Christoph

+1

Wow - tại sao tôi bao giờ bận tâm gọi là 'free()' sau đó?:-) – Justicle

Các vấn đề liên quan