这三行声明三个整数的内存,并初始化整数。如果您在函数之外执行此操作,您可以愉快地获取这些变量的地址并将它们存储在您的数组中。
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、&a 的地址),并且仅与将 &a 存储在 array_a[0] 中一样危险/无害,
array_b[0] = array_a[0];
释放array_a 是无害的,因为array_a 中没有存储任何可能“泄漏”的内容,并且不会影响array_b [0],因为它包含a 的地址,&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];