c-释放数组的已分配内存(与普通var?相比)



我知道,当我们为var分配内存时,我们需要用指向var的指针调用free()func来释放空间(而不是让指针悬空)。

但是,当我们为变量数组分配内存时,我们该怎么办呢?我们应该释放数组[0.n]的每个成员,还是只释放第一个成员的指针就足够了?

long *array_p; 
size_t elements_num = 5
array_p = malloc(elements_num*sizeof(long));

选项#1:

free(array_p);
array_p=NULL;

选项2:

for (i=0; i<array_len-1; ++i)
{
    free(array_p+i);
    array_p+i= NULL;
}

操作系统通常是这样工作的:除了实际/实际数据大小(包括一些额外信息,如分配的内存长度、下一次分配的可用内存地址等)之外,每次内存分配都会在内存块中留下一个跟踪。具体来说,

  • 当您分配一个40个字符的区块时,操作系统将分配56个字节——16个字节,以跟踪分配的内存长度、下一个可用(空闲)内存地址等,并为您的实际数据分配40个字节。

  • 然而,当您分配40个整数的块时,这一次操作系统将分配176个字节——同样是16个字节,以跟踪分配的内存长度、下一个可用(空闲)内存地址等,以及(4×40=)160个字节的实际数据。

因此,当您释放一个数据数组时,操作系统将已经知道要释放的内存的起始地址和结束地址。

这个视频的前20分钟非常详细地解释了这个过程。

问题不在于是否分配数组,而在于是否分配指针数组。

您使用的每个malloc/calloc都需要一个free。现在在这样的情况下

int* array = calloc(10, sizeof(int));

内存中有一个连续的10个int块,而您只需要一个free(array)

但是你可以有

int** arrayOfArray = calloc(10, sizeof(int*));

现在您有一个由10个int*组成的数组,因此指向int的指针。在实际情况下,您的数组不能使用,您必须分配或分配数组的每个元素,例如:

for (int i = 0; i < 10; ++i)
  arrayOfArray[i] = calloc(5, sizeof(int));

因此,第一个数组的每个元素都是指向5个int的连续内存块的指针。在这种情况下,你有两个级别的分配,实际上你需要两个级别,按照相反的顺序,例如:

for (int i = 0; i < 10; ++i)
  free(arrayOfArray[i]);
free(arrayOfArray);

但是,当我们为vars数组分配内存时,我们该怎么办呢?我们应该去释放数组[0.n]的每个成员,

是的,您必须free()数组中分配的每个指针。

还是仅仅为第一个成员释放指针就足够了?

没有。

例如,

char *p[50];
for(i = 0; i<50;i++)
p[i] = malloc(10); 

for(i = 0; i<50;i++)
free(p[i]);

char **p;
p = malloc(50 * sizeof(char*));
for(i = 0; i<50;i++)
p[i] = malloc(10); 
for(i = 0; i<50;i++)
free(p[i]);
free(p);

基本上,对malloc()的每一个调用,都有一个对free()的调用。

创建变量数组时,了解要创建的内容非常重要。在C中,指针的作用类似于数组,因此需要遍历整个数组,释放每个成员,然后释放第一个成员的指针。简单地将点释放到第一个成员而不释放数组的每个成员通常会导致内存泄漏,这可能最终导致程序运行缓慢,并最终崩溃或修改/访问您不打算修改的数据(分段错误)。

您只需将指向第一个元素(malloc给您的)的指针传递给free:

int * array = malloc(10 * sizeof(int));
....
free(array);

最新更新