2010-03-25 35 views
11

Bộ nhớ được cấp phát bằng malloc không tồn tại bên ngoài phạm vi chức năng?

Hi,

Tôi là một chút mới đến chức năng malloc C, nhưng từ những gì tôi biết điều đó nên lưu trữ các giá trị trong đống, vì vậy bạn có thể tham khảo nó với một con trỏ từ bên ngoài phạm vi ban đầu . Tôi đã tạo ra một chương trình thử nghiệm có nghĩa vụ phải làm điều này nhưng tôi tiếp tục nhận được giá trị 0, sau khi chạy chương trình. Tôi đang làm gì sai?

int f1(int * b) { 
b = malloc(sizeof(int)); 
*b = 5; 
} 

int main() { 
int * a; 
f1(a); 
printf("%d\n", a); 
return 0; 
} 

Trả lời

6

Bộ nhớ bản thân vẫn còn, nhưng nó bị rò rỉ bởi vì bạn không cung cấp con trỏ phân bổ cho người gọi. Ngoài ra, bạn đang in a khi bạn cần in *a. Cuối cùng, bạn không trả lại một int từ f1.

Hãy thử:

void f1(int **b) { 
*b = malloc(sizeof(int)); 
**b = 5; 
} 

int main() { 
int *a; 
f1(&a); 
printf("%d\n", *a); 
free(a); 
return 0; 
} 
0

Vấn đề của bạn là thực sự không liên quan đến malloc, mà là một thực tế rằng bạn đang đi qua các giá trị con trỏ hiện đang nắm giữ, chứ không phải là địa chỉ của nó. Hãy thử các cách sau:

int f1(int ** b) { 
    *b = malloc(sizeof(int)); 
    **b = 5; 
} 

int main() { 
    int * a; 
    f1(&a); 
    printf("%d\n", *a); 
    return 0; 
} 

Bằng cách chuyển giá trị con trỏ như bạn, không có cách nào cho giá trị malloc được tạo được lưu trữ vào con trỏ.

+3

Điều này một lần nữa được truyền theo giá trị. u r chuyển địa chỉ của một giá trị. ** Không vượt qua bằng cách tham chiếu trong C ** – raj

+0

Đủ công bằng. Cập nhật để chính xác hơn trong C. – Dusty

0

Địa chỉ int *b bị xóa khi hàm trả về. Để tiết kiệm nó, bạn cần phải sử dụng một con trỏ của một con trỏ

int f1(int ** b) { 
    *b = malloc(sizeof(int)); 
    **b = 5; 
} 
8

Có vẻ như bạn đang hiểu lầm là một phần cơ bản của cách C làm việc - cụ thể là rằng nó là một ngôn ngữ 'pass-by-value' . Để cho main() biết về bộ nhớ bạn đã phân bổ, bạn phải lấy lại bộ nhớ. Mã sau sẽ làm cho bạn những gì bạn muốn:

int f1(int **b) 
{ 
    *b = malloc(sizeof(int)); 
    **b = 5; 
} 

int main(int argc, char **argv) 
{ 
    int *a; 
    f1(&a); 
    printf("%d\n", *a); 
    return 0; 
} 

Có một vài khác biệt giữa mã này và của bạn; đầu tiên, chữ ký của f1() đã thay đổi, để nó có thể trả về kết quả của cuộc gọi malloc() trong con trỏ được chuyển. Tiếp theo, cuộc gọi tới f1() đã được thay đổi để chuyển địa chỉ của a thay vì a chính nó - quan trọng nếu bạn muốn nó được 'điền vào' bởi f1(), để nói. Cuối cùng, printf() trong main() đã được thay đổi để in ra giá trị được chỉ định thay vì chính con trỏ.

+7

Tôi đang thua lỗ vì sao mọi người đã nhảy thẳng vào sử dụng con trỏ tới con trỏ - đó là cách tốt nhất để giải thích cách thực hiện việc này cho người nào đó đang gặp sự cố với phần cơ bản của ngôn ngữ. Tại sao không chỉ trả về con trỏ từ 'f1()'? – caf

+0

@caf, vâng! đó là đơn giản cho một người mới bắt đầu hiểu. – raj

+0

Cảm ơn rất nhiều vì đã phản hồi mọi người! Mã của tôi hoạt động ngay bây giờ. Tôi không thể có chức năng trả lại con trỏ, bởi vì chức năng trong dự án thực tế của tôi nó đã trả lại một cái gì đó khác .. Cảm ơn một lần nữa! –

22

Có! a được truyền theo giá trị để con trỏ b chức năng f1 sẽ được địa phương .. hoặc trở b,

int *f1() { 
    int * b = malloc(sizeof(int)); 
    *b = 5; 
    return b; 
} 

int main() { 
    int * a; 
    a = f1(); 
    printf("%d\n", *a); 
    // keep it clean : 
    free(a); 
    return 0; 
} 

hoặc vượt qua a 's địa chỉ

int f1(int ** b) { 
    *b = malloc(sizeof(int)); 
    **b = 5; 
} 

int main() { 
    int * a; 
    f1(&a); 
    printf("%d\n", *a); 
    // keep it clean : 
    free(a); 
    return 0; 
} 
5

Hãy giả sử bạn gán một giá trị của NULL đến trước khi bạn gọi hàm f1.Bây giờ cách thức f1 được định nghĩa nó lấy đối số của nó (con trỏ đến một số int) theo giá trị. Đó là b sẽ là một loại khác là int * sẽ là sao chép của a. Vì vậy, b cũng sẽ có giá trị là NULL. Bây giờ trong f1 bạn thay đổi giá trị bằng b bằng cách gán cho nó địa chỉ bộ nhớ được cấp phát động bằng cách sử dụng malloc. Giả sử địa chỉ bộ nhớ là 0x123. Do chuyển nhượng này, b đã thay đổi giá trị của nó từ NULL thành 0x123 nhưng a (trong main) tiếp tục giữ NULL, vì thay đổi b sẽ không thay đổi a vì chúng là hai biến riêng biệt. Kết quả của việc này là khi bạn trở về từ hàm f1 một sẽ vẫn không thay đổi.

Có 2 cách để giải quyết vấn đề này. Một trong những bạn có thể làm cho hàm f1 trả về giá trị của số b đã thay đổi và sau đó gán nó vào một số main và hai, bạn có thể chuyển từng địa chỉ để bất kỳ thay đổi nào được thực hiện trong f1 cũng sẽ ảnh hưởng đến số main.

// f1 now returns the value of b. 
int* f1() { 
int *b = malloc(sizeof(int)); 
*b = 5; 
return b; 
} 

int main() { 
int *a = NULL; 
a = f1(); // assign the return value of f1 to a. 
printf("%d\n", *a); // prints 5...not its *a not just a. 
return 0; 
} 

.

// f1 now takes the address of a. 
void f1(int **b) { 
*b = malloc(sizeof(int)); // you are actually altering a indirectly. 
**b = 5; 
} 

int main() { 
int *a = NULL; 
f1(&a); // now pass the address of a to f1. 
printf("%d\n", *a); // prints 5...not its *a not just a. 
return 0; 
} 
Các vấn đề liên quan