C - 释放数组时指针数组会发生什么?

时间:2013-11-13 03:09:28

标签: c arrays pointers

我目前正在用C编程,我正在创建一个指针数组。数组中包含的这些指针将持续整个程序的持续时间。

让我们说指针数组是数组A.然后我创建另一个指针数组B,然后将数组A的元素放入数组B.然后,我释放数组A.

阵列B中的元素会发生什么?由于实际指针在内存中仍然有效,它是否已被释放,或者它仍然有效,它是否会再有效?

由于

以下是我的代码的示例 -

int a = 1;
int b = 2;
int c = 3;

int **array_a = (int **) malloc (sizeof (int *) * 3);
array_a[0] = &a;
array_a[1] = &b;
array_a[2] = &c;

int **array_b = (int **) malloc (sizeof (int *) * 1);
array_b[0] = array_a[0];
free(array_a);

现在,array_b [0]会发生什么?

5 个答案:

答案 0 :(得分:2)

如果你这样做

int *a = malloc(10 * sizeof(int));
for (int i = 0 ; i != 10 ; i++) {
    a[i] = 2*i+1;
}
int *b = a;
free(a);

然后b也将无效。

如果你这样做,不过

int *a = malloc(10 * sizeof(int));
for (int i = 0 ; i != 10 ; i++) {
    a[i] = 2*i+1;
}
int *b = malloc(10 * sizeof(int));
memcpy(b, a, 10 * sizeof(int));
free(a);

然后b仍然有效。

答案 1 :(得分:1)

指针本身不会改变,它仍指向指向的位置。唯一的事情是它指向的位置可能被分配给其他程序。您仍然可以使用未定义的行为来编写和读取位置。检查此代码:

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

int main()
{
    int *a = (int *)malloc(3 * sizeof(int));
    a[0] = 1, a[1] = 2, a[2] = 3;
    free(a);
    // a = NULL // if you add this, the following will crash.
    printf("%d\n", a[0]);
    printf("%d\n", a[1]);
    printf("%d\n", a[2]);
    return 0;
}

如果你很幸运,你仍然可以得到正确的结果。但这只是运气。

因此,在释放后将指针设置为NULL通常是个好主意。

答案 2 :(得分:0)

所以我不久前刚刚学到了一些关于free()的内容,所以我很遗憾地说我还不太了解它,但这里有一点我知道的事情:

要将动态分配的内存返回给系统,请使用free()函数。我的教授使用了这样的例子:

struct listNode *Bob;
Bob = &any instance of listNode;
free(Bob);

所以我相信B仍然有效,而A不再被引用。 Java会定期收集不再引用的动态分配的内存,并将其放入“垃圾”中。 C不这样做,这就是我们使用free()的原因。希望有点帮助。我还在学习自己。好问题:)

答案 3 :(得分:-1)

C将数组解释为基本元素的地址,因此根据您释放数组的方式,您可能根本没有释放该元素。

但是,假设您释放了数组中的所有元素,则数组B中的指针仍将存在(它仍将指向内存中的相同位置)。但是,你真的不知道那个位置是什么,因为你已经释放了那里的内存。您仍然可以获取存储在那里的原始数据,或者它可能已被覆盖。但是,使用它绝对不安全。

答案 4 :(得分:-1)

这三行为三个整数声明内存,并初始化整数。如果你在函数之外执行此操作,可以愉快地获取这些变量的地址并将它们存储在数组中。

int a = 1;
int b = 2;
int c = 3;

但是,如果在函数中(在堆栈上)声明上述三个变量并且您获取它们的地址,并将这些地址存储在某处,则会创建(潜在的)悬空指针问题。

这一行分配足够的内存来保存三个指向int(12或24字节)的指针,

int **array_a = (int **) malloc (sizeof (int *) * 3);

现在将先前定义的变量a,b,c的地址存储到array_a [],

array_a[0] = &a;
array_a[1] = &b;
array_a[2] = &c;

根据声明a,b,c的位置,这完全无害或非常危险,例如,

int** youfun()
{
    int a = 1;
    int b = 2;
    int c = 3;
    int **array_a = (int **) malloc (sizeof (int *) * 3);
    array_a[0] = &a;
    array_a[1] = &b;
    array_a[2] = &c;
    return(array_a); //very bad!
}

int a = 1;
int b = 2;
int c = 3;
int** mefun()
{
    int **array_a = (int **) malloc (sizeof (int *) * 3);
    array_a[0] = &a;
    array_a[1] = &b;
    array_a[2] = &c;
    return(array_a); //safe, but strange
}

为array_b []声明和分配空间,并保留单个内存位置类似于指向int的一个指针的声明和数组,

int **array_b = (int **) malloc (sizeof (int *) * 1);

以下赋值放置了array_a [0]的内容(它是变量a的地址,&amp; a,来自上面),并且只有将&amp; a存储在array_a [0]中一样危险/无害,

array_b[0] = array_a[0];

释放array_a是无害的,因为array_a中没有任何内容可能会“泄漏”,并且不会影响array_b [0],因为它包含a,&amp; a,

的地址
free(array_a);

假设您执行了以下操作,

int **array_a = (int **) malloc (sizeof (int *) * 100);
int ndx;
for(ndx=0; ndx<100; ++ndx)
    array_a[ndx] = malloc( sizeof(int) );

您现在已经分配了100 + 1个内存位置,这仍然很好。

然后假设您分配的array_b将有足够的空间来容纳所有的array_a [],

int **array_b = (int **) malloc (sizeof (int *) * 100);
int ndx;
for(ndx=0; ndx<100; ++ndx)
    array_b[ndx] = malloc( sizeof(int) );

这会泄漏内存(由array_b指向),加上每个array_b [ndx]指向的内存,总计100 + 1内存位置泄漏,

array_b = array_a; //discarded memory references at array_b[0..99], and array_b

现在假设你做了这两件事,

array_b = array_a; //you just discarded the memory references at array_b[0..99] and array_b
free(array_a); //you just discarded array_a[0..99]

上面会泄漏array_b,array_b [0..99]指向的所有内存和array_a [0..99]的所有内存,因为你只复制了array_a的地址,而不是array_a [0..99]的地址]

以下是如何复制在array_a [0..99],

中分配的内存
for(ndx=0; ndx<100; ++ndx)
    array_b[ndx] = array_a[ndx];