我目前正在用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]会发生什么?
答案 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];