2009-08-20 67 views
10

Tôi biết chúng ta nên giải phóng bất kỳ biến nào được phân bổ với malloc, nhưng nếu tôi trả về biến đó trong một hàm thì sao? Một cái gì đó như thế này:Trả về biến được phân bổ

char *somefunction(int somearg){ 
    char *str; 

    str=(char *)malloc(sizeof(char *)); 

    //some code 

    return str; 
} 

Tôi có nên tự do không? Làm thế nào tôi có thể làm điều đó?

+2

Đối số 'malloc()' gần như chắc chắn sai - bạn phân bổ đủ bộ nhớ để lưu trữ 'char *', nhưng gán cho một con trỏ trỏ tới 'char' (và không cần phải trả lại giá trị của 'malloc' trong C, hoặc là). 'str = malloc (N * sizeof * str);' là cách tốt hơn để viết nó. – caf

+0

Như CAF đã nói, bạn không nên bỏ giá trị trả về của malloc(). Xem http://stackoverflow.com/questions/1565496/specifically-whats-dangerous-about-casting-the-result-of-malloc et al – Mawg

Trả lời

13

Bạn có hai tùy chọn: một, chuyển char * đến một số chức năng và sử dụng thay vì phân bổ trong một số chức năng, hoặc hai, miễn phí giá trị trả lại sau này.

Tùy chọn đầu tiên:

char *somefunction(char *str, int somearg){ 

    //some code 

    return str; 
} 

// Elsewhere... 
char *str = (char *) malloc....; 
somefunction(str, 123); 
// Code... 
free(str); 

Lựa chọn thứ hai:

char *somestr = somefunction(123); 
// Do something... 
free(somestr); 

Cá nhân tôi đề nghị tùy chọn đầu tiên, vì nó là một chút dễ dàng hơn để tránh bộ nhớ bị rò rỉ khi nó không được phân bổ trong các chức năng tùy ý .

+1

Câu trả lời hay (và câu hỏi), tôi tình cờ gặp vấn đề tương tự gần đây. Một câu hỏi: Điều gì sẽ xảy ra nếu khó xác định trước bao nhiêu bộ nhớ mà giá trị trả về của hàm cần? Sau đó, nó sẽ có vẻ tự nhiên hơn để phân bổ trong chức năng; nếu không bạn sẽ cần xử lý lỗi trong hàm cho trường hợp không gian bộ nhớ được cung cấp quá nhỏ (ví dụ: để trả về một chuỗi có độ dài biến đổi). – sleske

+0

Chuỗi có độ dài thay đổi có thể biện minh cho bộ nhớ được cấp phát trong hàm. Tôi sẽ rất do dự về mã như vậy trong dự án của riêng tôi tuy nhiên, và thay vì thích xác định rõ ràng một chiều dài tối đa được chọn dựa trên bối cảnh và các yêu cầu của mã. Bạn đang nói về loại chuỗi dài nào? Họ không thể có nhiều hơn một vài KB/MB có thể được phân bổ trước? –

2

Bạn nên giải phóng tất cả không gian được phân bổ nhưng nếu bạn trả lại vì bạn sẽ sử dụng không gian bộ nhớ đó trong các phần khác của chương trình, vì vậy sau khi sử dụng, bạn sẽ được miễn phí. Xem mọi nơi trong mã gọi hàm và giải phóng dung lượng sau khi bạn sử dụng giá trị trả về.

2

Nếu bạn dự định trả lại địa chỉ của khối, bạn không nên miễn phí() khối mà thay vào đó hãy dựa vào mã gọi để giải phóng() sau này. Điều này được gọi là đi qua trên tàu.

Nếu bạn giải phóng nó trong hàm và trả về con trỏ, mã gọi sẽ chạy vào hành vi không xác định đang cố truy cập khối đã giải phóng.

4

Bạn giải phóng nó khi bạn đã hoàn thành nó. Không có quy tắc nào nói rằng hàm free() khớp với một malloc() phải nằm trong cùng một hàm.

+0

vì vậy, tôi có thể làm một cái gì đó như miễn phí (str) ra khỏi chức năng hoặc miễn phí (somefunction)? –

+1

Có thực sự. Cũng giống như bạn có thể làm với malloc(), đó là sau khi tất cả chỉ là một chức năng khác. –

2

Đây là một thực tế đối với một số chức năng hiện có (ví dụ: strdup()) nhưng thường là một ý tưởng tồi. Yêu cầu người dùng phải nhận thức được những gì xảy ra bên trong một cuộc gọi hàm là một yêu cầu không tốt - hãy nghĩ xem có bao nhiêu chức năng mà bạn sử dụng những người bên trong bị ẩn khỏi bạn. Nói chung, bạn sẽ muốn có một người dùng vượt qua trong một bộ đệm và kích thước thay vì phân bổ bộ nhớ cho họ.

+1

Đồng ý, nhưng điều gì sẽ xảy ra nếu khó quyết định trước bao nhiêu không gian cần thiết (ví dụ: tạo động một chuỗi sẽ được trả lại). Sau đó, nó sẽ có vẻ tự nhiên hơn (và đơn giản hơn) cho chức năng phân bổ bộ nhớ nhiều như nó cần. Bạn nghĩ sao? – sleske

+0

Một điểm rất tốt. Tuy nhiên, trên thực tế, sẽ luôn có độ dài trên được biết đến, vì nó sẽ phải phù hợp với trường cơ sở dữ liệu hoặc trên màn hình hoặc đầu ra được định dạng. Tất nhiên, thật lãng phí khi phân bổ 255 byte khi bạn chỉ có thể cần một, vì vậy nó phụ thuộc vào những gì bạn đang thực hiện. Tôi sẽ không lo lắng quá nhiều trong một ứng dụng Windows, nhưng một hệ thống nhúng trên một vi 8-bit là một ấm đun nước khác nhau của những con ngựa màu. – Mawg

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