2010-08-29 28 views
7

Trong dự án của tôi, tôi có một phương thức tạo chuỗi từ các số nguyên (sử dụng strcat) và ghi nó vào một tệp. Thật không may nó có một rò rỉ bộ nhớ. Trong khi theo dõi sự rò rỉ đó, tôi đã đơn giản hóa mã của mình như sau. Tôi dường như không thể xác định vị trí hoặc thậm chí sửa chữa nó. Đây là mã:Lỗ hổng bộ nhớ trong mã này ở đâu và cách khắc phục?

#include <stdio.h> 
#include <stdlib.h> 
#include <string.h> 
int main(int argc, char* argv[]) 
{ 
char* output = "\0"; 
int counter = 5; 
    while(counter > 0) 
    { 
     char buffer[20]; 
     sprintf(buffer, "%u", counter); 
     char* temp; 
     temp = malloc((strlen(output) + strlen(buffer) + 1)); 
     strcpy(temp, buffer); 
     strcat(temp, output); 
     char* oldmemory = output; 
     output = temp; 
     free(oldmemory); 
     counter--; 
    } 
printf("output: %s\n", output); 
free(output); 
return 0; 
} 

Valgrind lợi nhuận:

==7125== Memcheck, a memory error detector 
==7125== Copyright (C) 2002-2009, and GNU GPL'd, by Julian Seward et al. 
==7125== Using Valgrind-3.6.0.SVN-Debian and LibVEX; rerun with -h for copyright info 
==7125== Command: ./foo 
==7125== Parent PID: 4455 
==7125== 
==7125== Invalid free()/delete/delete[] 
==7125== at 0x4024B3A: free (vg_replace_malloc.c:366) 
==7125== by 0x8048662: main (foo.c:20) 
==7125== Address 0x8048780 is not stack'd, malloc'd or (recently) free'd 
==7125== 
==7125== 
==7125== HEAP SUMMARY: 
==7125==  in use at exit: 0 bytes in 0 blocks 
==7125== total heap usage: 5 allocs, 6 frees, 20 bytes allocated 
==7125== 
==7125== All heap blocks were freed -- no leaks are possible 
==7125== 
==7125== For counts of detected and suppressed errors, rerun with: -v 
==7125== ERROR SUMMARY: 1 errors from 1 contexts (suppressed: 15 from 8) 

là rò rỉ bộ nhớ và làm thế nào tôi có thể sửa chữa nó ở đâu?

Trả lời

9
#include <stdio.h> 
#include <stdlib.h> 
int main(int argc, char* argv[]) 
{ 
char* output = "\0"; 

Chuỗi chữ '\ 0' tự động chấm dứt, bạn không cần phải thêm nó.

int counter = 5; 
    while(counter > 0) 
    { 
     char buffer[20]; 
     sprintf(buffer, "%u", counter); 
     char* temp; 
     temp = malloc((strlen(output) + strlen(buffer) + 1)); 
     strcpy(temp, buffer); 
     strcat(temp, output); 
     char* oldmemory = output; 
     output = temp; 
     free(oldmemory); 

Lần đầu tiên free() này được gọi, nó giải phóng các giá trị ban đầu của đầu ra, mà là một con trỏ đến một chuỗi chữ "\0". Gọi số free() vào bất kỳ thông tin nào khác ngoài con trỏ hợp lệ được trả về từ *alloc() hoặc NULL là hành vi không xác định.

 counter--; 
    } 
printf("output: %s\n", output); 
free(output); 
return 0; 
} 

báo cáo valgrind:

==7125== Invalid free()/delete/delete[] 
==7125== at 0x4024B3A: free (vg_replace_malloc.c:366) 
==7125== by 0x8048662: main (foo.c:20) 
==7125== Address 0x8048780 is not stack'd, malloc'd or (recently) free'd 

Đây không phải là một rò rỉ bộ nhớ; đó là số free() không hợp lệ.

+0

+1 để được giải thích rõ ràng. – RBerteig

3

Ứng dụng của bạn đang gặp sự cố khi cố gắng giải phóng ("\ 0"). (Chỉ cần một lưu ý, nếu bạn muốn một chuỗi rỗng, "" là đủ, "\ 0" thực sự là chuỗi \ 0 \ 0.

Thay vì sử dụng malloc và strcpy, nhìn vào realloc, nó làm mọi thứ bạn muốn nhưng tốt hơn :) Nhưng bạn có nhiều khả năng muốn xây dựng chuỗi của bạn về phía trước (counter = 0; counter < 5; count ++) thay vì đi ngược lại

+3

Ngoại trừ thất bại realloc trả về NULL, vì vậy bạn phải xem các rò rỉ trong trường hợp bạn làm 'p = realloc (p, new_size)'. –

+0

@Roger: thất bại 'realloc' có thể có nghĩa là chương trình phải chấm dứt một cách duyên dáng. Đừng nghĩ rằng một rò rỉ bộ nhớ sau đó là có liên quan nhiều. –

+0

Nó không khó để nắm bắt rò rỉ tiềm năng với 'realloc', chỉ cần giữ một bản sao của con trỏ ban đầu qua cuộc gọi để nó có thể được giải phóng. Hoặc, giả sử rằng một 'realloc' thất bại có nghĩa là kết thúc của thế giới, và chỉ cần thoát ra. Cá nhân tôi thích sử dụng 'assert()' cho kiểm tra đó, vì nó đảm bảo lối ra là một sự thất bại đáng chú ý. – RBerteig

4

Mã của bạn bị hỏng. Việc đầu tiên đi qua, bạn thiết lập oldmemory để đầu ra nơi đầu ra chỉ vào bộ nhớ không được cấp phát trên heap. Sau đó, bạn cố gắng giải phóng bộ nhớ này. Điều này tạo ra lỗi valgrind về giải phóng bộ nhớ không được cấp phát qua malloc. Do đó, bộ nhớ ban đầu bạn phân bổ không bao giờ được giải phóng.

+0

Tôi nghĩ rằng anh ấy/cô ấy biết nó bị hỏng. Không cần phải thô lỗ về nó. –

+0

WTF? Làm thế nào là những gì tôi đã viết là thô lỗ? Tôi nghĩ rằng bạn đã có máy dò độ nhạy của bạn thiết lập chỉ là một chút quá cao. Hay tôi đang thô lỗ vì chỉ ra điều đó. Có lẽ bạn đã biết điều đó. – sizzzzlerz

+0

Lol không cần phải bắt đầu ngẫu nhiên xuống bỏ phiếu cho câu hỏi của tôi, bitch –

1

Nếu bạn muốn sử dụng thuật toán này, các không gian ban đầu cho những gì điểm đầu ra nên được phân bổ với malloc, thusly:

char *output = malloc(1); 
if(!output) { /* handle error */ } 
output[0] = '\0'; 
... rest of code as is ... 

literals chuỗi không phân bổ với malloc, và do đó không thể free 'ed, đó là nguồn gốc của vấn đề của bạn.

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