2014-06-10 95 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可以打印如果另一个值的地址内存区域被修改。