2010-03-25 40 views
11

分配malloc的內存不會在函數範圍外持久存儲嗎?

嗨,

我有點新的C的malloc函數,但是從我知道它應該值存儲在堆,這樣你就可以從原來的範圍之外的指針引用它。我創建了一個應該這樣做的測試程序,但在運行該程序後我一直得到值0。我究竟做錯了什麼?

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

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

回答

6

內存本身仍然存在,但它泄漏,因爲你沒有提供所分配的指針調用者。另外,當您應該打印*a時,您正在打印a。最後,你不是從f1返回一個int。

嘗試:

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

你的問題實際上是不相關的malloc,而是你傳遞指針目前持有的價值,而不是它的地址的事實。請嘗試以下操作:

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

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

通過傳遞指針值,您無法將創建的malloc值存儲到指針中。

+3

這再次通過價值。你傳遞一個值的地址。 ** C ** – raj 2010-03-25 05:35:46

+0

沒有通過引用傳球。更新爲在C中更準確。 – Dusty 2010-03-25 12:50:07

0

當函數返回時,地址int *b被刪除。要保存它,你需要使用一個指針

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

它看起來像你的誤解ç是如何工作的一個基本組成部分的指針 - 即它是一個「傳址值的語言。爲了讓main()知道您分配的內存,您必須將其重新取出。以下代碼會爲你做什麼:

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; 
} 

這段代碼和你的代碼有幾點區別,首先,f1()的簽名已經更改,以便它可以返回malloc()調用的結果在傳入的指針中。接下來,撥打f1()已更改爲通過a而不是a本身的地址 - 這一點很重要,如果您希望它由f1()「填充」,可以這麼說。最後,printf()main()已被更改爲打印出指向的值而不是指針本身。

+7

我不知道爲什麼每個人都直接跳到使用指針指針 - 這不是解釋如何做到這一點的最好方式,以幫助那些遇到更多問題的人語言的基本部分。爲什麼不直接從'f1()'返回指針呢? – caf 2010-03-25 05:29:08

+0

@caf,是的!對初學者來說這很簡單。 – raj 2010-03-25 05:31:27

+0

非常感謝大家的反饋!我的代碼現在可用。 我不能讓函數返回指針,因爲我的實際項目中的函數已經返回其他東西了。 再次感謝! – 2010-03-25 05:40:55

22

是的! a按值傳遞所以在功能f1指針b將是本地.. 要麼返回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; 
} 

或通過a的地址

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

讓我們假設你分配一個值的NULL到之前你調用函數f1。現在f1被定義的方式是它的參數(指向int的值)。那就是b將是int *類型的另一個變量,它將是拷貝a。因此b也將具有值NULL。現在在f1中,通過爲其分配使用malloc動態分配的內存地址,將值更改爲b。可以說,內存地址是0x123。作爲此作業的結果,b已將其值從NULL更改爲0x123,但a(在main中)繼續保留NULL,因爲更改b將不會更改a,因爲它們是兩個單獨的變量。因此,當您從功能f1返回時,a將保持不變。

有兩種方法可以解決這個問題。您可以使功能f1返回已更改的b的值,然後將其分配回main中的一個和兩個,您可以傳遞該地址以便在f1中進行的任何更改也會影響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; 
}