2015-04-15 16 views
10

Tôi đã tạo một hàm được thiết kế để nhận dữ liệu nhập của người dùng. Nó yêu cầu bộ nhớ được cấp phát cho biến giữ đầu vào của người dùng; tuy nhiên, biến đó được trả về ở cuối hàm. Phương pháp thích hợp để giải phóng bộ nhớ được phân bổ/trả về giá trị của biến là gì?Cách thích hợp để bộ nhớ miễn phí của biến số được trả lại

Đây là mã:

char *input = malloc(MAX_SIZE*sizeof(char*)); 
int i = 0; 
char c; 

while((c = getchar()) != '\n' && c != EOF) { 
    input[i++] = c; 
} 

return input; 

Tôi có nên trả về địa chỉ của đầu vào và miễn phí nó sau khi nó được sử dụng?

Tò mò là phương pháp thích hợp nhất để giải phóng biến đầu vào.

+0

Nếu bạn 'malloc', cuối cùng ai đó sẽ cần phải 'tự do', có thể là bạn trong một api khác hoặc người gọi. Liên quan, nếu được hỗ trợ trên (các) nền tảng đích của bạn, ['getline'] (http://pubs.opengroup.org/stage7tc1/functions/getdelim.html), một hàm thư viện được thêm vào POSIX.1-2008, có vẻ như để * gần * làm những gì bạn đang cố gắng triển khai. Nó vẫn yêu cầu người gọi để cuối cùng 'miễn phí' bất kỳ phân bổ trả lại, nhưng cũng cung cấp ngữ nghĩa tái sử dụng, nơi mã của bạn không * không *. Tùy thuộc vào mục đích sử dụng và nền tảng đích, nó có thể đáng xem xét. – WhozCraig

Trả lời

11

Nó khá đơn giản, miễn là bạn chuyển đến free() cùng một con trỏ được trả lại bởi malloc() thì tốt.

Ví dụ

char *readInput(size_t size) 
{ 
    char *input; 
    int chr; 
    input = malloc(size + 1); 
    if (input == NULL) 
     return NULL; 
    while ((i < size) && ((chr = getchar()) != '\n') && (chr != EOF)) 
     input[i++] = chr; 
    input[size] = '\0'; /* nul terminate the array, so it can be a string */ 
    return input; 
} 

int main(void) 
    { 
    char *input; 
    input = readInput(100); 
    if (input == NULL) 
     return -1; 
    printf("input: %s\n", input); 
    /* now you can free it */ 
    free(input); 
    return 0; 
    } 

gì bạn không bao giờ nên làm là một cái gì đó giống như

free(input + n); 

input + n không phải là sự trở lại con trỏ bởi malloc().

Nhưng mã của bạn, có những vấn đề khác bạn nên chăm sóc

  1. Bạn đang phân bổ không gian cho MAX_SIZEchar s vì vậy bạn nên nhân với sizeof(char) đó là 1, thay vì sizeof(char *) mà sẽ phân bổ MAX_SIZE con trỏ, và thay vào đó, bạn có thể thực hiện một tham số chức năng MAX_SIZE, vì nếu bạn đang phân bổ bộ đệm cố định, bạn có thể xác định mảng trong main() với kích thước MAX_SIZE như char input[MAX_SIZE] và chuyển nó tới readInput(). r, do đó tránh malloc()free().

  2. Bạn đang phân bổ không gian nhiều nhưng bạn không ngăn chặn tràn trong while vòng lặp của bạn, bạn nên xác minh rằng i < MAX_SIZE.

+0

Ông không thể sử dụng mảng cục bộ, vì khi nó trở về và khung ngăn xếp của hàm bị hủy, sẽ không có cách nào đảm bảo mảng sẽ được giữ nguyên. Trình biên dịch sẽ cung cấp cho bạn một cảnh báo: "hàm trả về địa chỉ của biến cục bộ [-Wreturn-local-addr]". Khác hơn thế, câu trả lời hay. –

+1

@EnzoFerber Tôi có nghĩa là vượt qua mảng để chức năng và điền nó ở đó, tôi biết rằng bạn không phải trả lại một mảng địa phương. Tôi nghĩ tôi cần làm rõ điều đó. –

4

Bạn có thể viết một hàm với sự trở lại loại char*, trở input, và yêu cầu người dùng gọi free một lần thực hiện của họ với các dữ liệu.

Bạn cũng có thể yêu cầu người dùng tự chuyển vào bộ đệm có kích thước phù hợp, cùng với giới hạn kích thước bộ đệm và trả về số lượng ký tự được ghi vào bộ đệm.

-1

Đây là trường hợp điển hình. Một bộ nhớ mallocs chức năng cho kết quả của nó, người gọi phải giải phóng giá trị trả về. Bây giờ bạn đang đi bộ trên băng mỏng của rò rỉ bộ nhớ c. 2 lý do

Đầu tiên; không có cách nào để bạn có thể truyền đạt yêu cầu miễn phí theo cách thực thi (tức là trình biên dịch hoặc thời gian chạy không thể giúp bạn - tương phản với việc xác định loại đối số).Bạn chỉ cần ghi lại tài liệu của mình ở đâu đó và hy vọng người gọi đã đọc tài liệu của bạn

Thứ hai: ngay cả khi người gọi biết cách giải phóng kết quả, người đó có thể mắc lỗi, một số đường dẫn lỗi sẽ không giải phóng bộ nhớ. Điều này không gây ra một lỗi ngay lập tức, mọi thứ dường như làm việc, nhưng sau khi chạy trong 3 tuần ứng dụng của bạn bị treo sau khi hết bộ nhớ

Đây là lý do tại sao rất nhiều ngôn ngữ 'hiện đại' tập trung vào chủ đề này, C++ con trỏ thông minh, Java, C#, etc garbage collection, ...

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