2014-06-10 79 views
2

我在C編程中非常新,我正在玩malloc(),free()和指針分配,以便更好地掌握它。C指針分配malloc()和free()C

這裏是我的代碼:

#include <stdio.h> 
#include <stdlib.h> 

#define SIZE 10 

void 
array_fill(int * const arr, size_t n) 
{ 
    size_t i; 
    for (i = 0; i < n; i++) 
    arr[i] = i; 
} 

void 
array_print(const int * const arr, size_t n) 
{ 
    size_t i; 
    for (i = 0; i < n; i++) 
    printf("%d ", arr[i]); 

    printf("\n"); 
} 


int 
main(int argc, char ** argv) 
{ 
    int * p1, * p2; 

    p1 = (int *) malloc(SIZE * sizeof(int)); 
    p2 = p1; 

    array_fill(p1, SIZE); 
    array_print(p1, SIZE); 
    array_print(p2, SIZE); 

    printf("\nFREE(p1)\n"); 
    free(p1); 

    array_print(p2, SIZE); 

    return (0); 
} 

gcc test.c -o test編譯它,並./test運行它:

0 1 2 3 4 5 6 7 8 9 
0 1 2 3 4 5 6 7 8 9 

FREE(p1) 
0 0 2 3 4 5 6 7 8 9 
  1. p2 = p1,豈不是p2指向相同的值p1
  2. 解放後p1爲什麼我仍然可以打印p2(索引1的值是不同的)?我是否會導致內存泄漏或指針懸空?
  3. 這是正常的能打印p2即使p1被釋放?
+1

可能的重複:[我們如何能夠在釋放內存後訪問指針?](http://stackoverflow.com/questions/22033822/how-are-we-able-to-access-the-pointer-解除後分配內存) –

回答

3

p2 = p1,豈不是p2指向相同的值p1

是的,分配後兩個指針指向相同的內存區域。

釋放p1後,爲什麼我仍然可以打印p2(指數1爲不同的值)?我是否會導致內存泄漏或指針懸空?

是的,一旦你免費p1p2指針變得懸空。通過它訪問任何東西都是未定義的行爲。

這是正常的能夠打印p2,即使p1被釋放?

不,這是未定義的行爲。

不要讓你看到的數字看起來像以前讓你迷惑的數字:與之前調用free之前出現的數字的任何相似都是完全的巧合。不幸的是,像這樣的巧合使懸掛指針的問題非常難以找到。爲了解決這個問題,內存分析器程序接管了free-d區域,並有意識地在其中寫入一些垃圾值。這使檢測更快,但它不是防彈的。

+0

感謝您的輸入,一個問題是,這是程序員的責任,以確保不使用'p2'或是否有辦法自動避免這種情況? – user3727663

+0

@ user3727663不幸的是,在C中沒有簡單的方法來避免這種情況,所以確保通過懸掛指針訪問不會發生仍然是程序員的責任。 – dasblinkenlight

3

1)是

2)您正在訪問釋放的內存是一件壞事。

3)行爲未定義。它可以工作,它可能會崩潰,它可以打印垃圾,也可能我們都吸進黑洞(雖然不太可能)

+0

感謝您的回答。將'p1'設置爲'NULL'後,有沒有辦法讓'p2'自動指向'NULL'? – user3727663

+0

不是我所知道的。通常的做法是通過在空閒後將NULL設置爲NULL來使指針無效,但這並沒有什麼幫助,因爲指針變量傳遞給free是不成問題的。 – DrC

2
  1. 是的,p2指向與p1相同的區域。
  2. 顯然,內存被釋放,但它還沒有被重用(儘管一個值已被覆蓋)。釋放內存後,您不應該通過另一個指針訪問它。
  3. 它可能導致未定義的行爲。在你的情況下,它打印損壞的數組。它也可能因分段錯誤而崩潰(如果內存頁面不再屬於您的應用程序)。行爲可能會根據操作系統,編譯器和其他東西而改變,所以最好避免這種做法。
1

1)存儲在指針中的值是存儲器地址。這意味着,具有相同值的兩個指針指向相同的地址,這意味着相同的內存區域。

2)解放了指針p1唯一的p1值設置爲NULL,並說內存指向p1是免費使用的,它不再保留。但它並沒有抹掉記憶。它仍然持有它的價值。但是通過另一個仍然有地址的指針訪問它是一個未定義的行爲,因爲它可以被保留用於其他事情。 3)是的,這是正常的,因爲它已經在(2)中解釋了;的存儲器區域也不會被擦除或設置爲0 S和p2仍然指向這意味着它仍然打印相同值

注意,如果存儲區域由後保留由malloc,印刷p2可以打印如果另一個值的地址內存區域被修改。