当使用realloc减少数组时,内存会发生什么?

时间:2018-12-25 13:05:13

标签: c arrays memory free realloc

我想知道当您重新分配-1您的数组时内存会发生什么。根据我所读过的有关realloc的所有知识,我想指针仍然指向内存中的同一位置(因为函数可用且足够,因此无需函数来寻找另一块内存),请告诉我我是否错了。我的问题是:被删除的数组是否被删除(如使用free()一样),或者值保持不变,并且该内存被共享以用于将来的malloc,calloc等操作?

编辑: 我还有一个问题。此功能正常工作吗?它应该删除先前由数组的下一个元素覆盖的数组元素。在整个数组上执行此操作,最后一个元素与最后一个元素相同,最后一个元素被删除。 PicCounter是已经上传到程序的图片数。检查一下:

int DeletePicture(struct Picture **tab, int *PicCounter)
{
int PicToDelete;
printf("Enter the number of pic to delete ");
scanf("%d", &PicToDelete);
for (int i = PicToDelete - 1; i < (*PicCounter) - 2; i++)
{
    (*tab)[i] = (*tab)[i + 1];
}

struct Picture *temp;
temp = realloc(*tab, ((*PicCounter)-1) * sizeof(*temp));
if (temp != NULL)
{
    *tab = temp;
 //That doesn't delete the element, because in main I can still print it
 //like e.g. tab[lastelement]. 
    (*PicCounter)--;
    printf("Picture has been deleted\n");
    return 0;
}
else
{
    printf("Memory reallocation error\n");
    return 1;
}
}

1 个答案:

答案 0 :(得分:3)

关于void *realloc(void *ptr, size_t size),C标准在C 2018 7.22.3.5第2和第3段中说:

  

realloc函数释放由ptr指向的旧对象,并返回一个指向新对象的指针,该对象的大小由size指定。在重新分配之前,新对象的内容应与旧对象的内容相同,直到新旧大小中的较小者为止。新对象中超出旧对象大小的任何字节都具有不确定的值。

     

如果ptr是空指针,则对于指定的大小,realloc函数的行为类似于malloc函数。否则,如果ptr与内存管理函数先前返回的指针不匹配,或者如果通过调用freerealloc函数释放了空间,则该行为是不确定的。如果size非零,并且未分配新对象的内存,则不会释放旧对象。如果size为零,并且未分配新对象的内存,则是否释放旧对象由实现定义。如果未释放旧对象,则其值将保持不变。

当您要求减小先前分配的对象的大小时,这意味着:

  • 返回的指针可能与原始指针相同或不同。 (请参见下面的讨论。)

  • C标准允许释放的内存部分重新用于其他分配。是否重复使用取决于C的实现。

  • C标准未指定是否立即覆盖内存释放部分中的值。当然,realloc的用户可能不依赖于有关该内存的任何行为。

讨论

当减少内存分配时,对于内存分配例程来说,简单地返回相同的指针,同时记住释放的内存是空闲的,这显然是“容易的”。但是,内存分配系统相当复杂,因此可能会涉及其他因素。例如,假设:

  • 为了在不增加开销的情况下支持许多小的分配,内存分配系统可能会创建一个内存池,用于一到四个字节的分配,另一个池用于五到八,另一个池用于八到八。 16,以及用于较大尺寸的通用池。对于较大的大小,它可能会分别记住每个分配,自定义其大小并使用各种数据结构来管理它们。对于较小的大小,每个位可能只保留一个位图,每个位指示是否分配了其相应的四字节(或八个或16个)区域。在这样的系统中,如果释放16字节分配中的8个字节,则内存分配软件可能会将数据移至8字节池中的某个位置。

  • 在任何内存分配系统中,如果在分配末尾仅释放几个字节,则可能没有足够的字节来利用—跟踪释放的几个字节所需的数据结构可能是大于几个字节。因此,使其可重用是不值得的。内存分配系统只是将它们与块保持在一起,尽管它可能会记住该块中的数据实际上比为其保留的空间小。