我的教授给了我们一个“作业”,找出为什么realloc()
在这个具体的例子中不起作用。
我尝试搜索这个网站,我认为它不会起作用,因为没有真正的方法来确定用malloc()
分配的内存块的大小,因此realloc()
不知道新的大小需要重新分配的内存块。
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <windows.h>
int main ()
{
MEMORYSTATUS memInfo;
memInfo.dwLength = sizeof(MEMORYSTATUS);
GlobalMemoryStatus(&memInfo);
double slobodno = memInfo.dwAvailVirtual/1024./1024.;
printf("%g MB\n",slobodno);
int br=0,i,j;
char **imena,*ime,*temp,*bbb=NULL;
imena=(char**) malloc(sizeof(char*)*(br+1));
while(1)
{
printf("Unesite ime: ");
ime=(char*) malloc(sizeof(char)*4000000);
gets(ime);
printf("%u\n", strlen(ime));
ime=(char*) realloc(ime,strlen(ime)+1);
GlobalMemoryStatus(&memInfo);
slobodno = memInfo.dwAvailVirtual/1024./1024.;
printf("%g MB\n",slobodno);
if (strcmp(ime,".")==0)
{free(ime);free(imena[br]);break;}
imena[br++]=ime;
imena=(char**) realloc(imena,sizeof(char*)*(br+1));
}
for (i=0;i<br-1;i++)
for (j=i+1;j<br;j++)
if (strcmp(imena[i],imena[j])>0)
{
temp=imena[i];
imena[i]=imena[j];
imena[j]=temp;
}
//ovde ide sortiranje
for (i=0;i<br;i++)
printf("%s\n",imena[i]);
for(i=0;i<br;i++)
free(imena[i]);
free(imena);
return 0;
}
注意:教授添加了用于打印可用内存的行,因此我们可以看到realloc()
不起作用。我们输入的每个新字符串只占用sizeof(char)+4000000
个字节,无法重新分配。我试图找出原因。提前致谢
答案 0 :(得分:3)
我觉得它与Windows上的页面大小有关。 例如,如果将4000000更改为400000,则可以看到可以重复使用内存。
我认为分配4000000迫使Windows使用“巨大的”页面大小(4MB)和某些(我不知道)的原因,realloc不会以你期望的方式对它们起作用(即制作未使用的内存)可用于其他分配)。
这似乎与提到VirutalAlloc的Realloc() does not correctly free memory in Windows有关,但我不确定它是否说明realloc不起作用的确切原因。
答案 1 :(得分:0)
来自MSDN:
memblock
参数指向内存块的开头。如果memblock
为NULL
,则realloc
的行为与malloc
相同,并分配一个新的size
字节块。
所以ime=(char*) realloc(NULL,sizeof(char)*4000000);
行每次只有malloc
的新记忆。
答案 2 :(得分:0)
问题不在于realloc不知道原始块的大小。即使我们的程序员无法获得该信息,也需要重新分配(即使该块使用malloc或calloc分配)。
该行
ime=(char*) realloc(ime,strlen(ime)+1);
看起来正在缩小先前分配的块以准确地拟合内容,但是没有要求实际上缩小内存块并使剩余部分再次可用于新分配。
修改强>
我刚才想到的另一件事:使用realloc缩小可能会正常工作,但运行时库不会将内存返回给操作系统,因为库会保留它以供下次分配。 只是,下一个分配是针对这么大的块,它不适合使用realloc释放的内存。
答案 3 :(得分:0)
realloc
没有释放内存。当您调用realloc
/ malloc
/ calloc
时,这些函数可以使用大块内存(称为&#34;堆&#34;)并刻出块。如果此时需要的内存多于堆中的内存,则通过向操作系统请求更多内存来扩展堆。
当您致电realloc
以缩小内存块时,所发生的一切就是*alloc
可以使用不再需要的内存再次发送给不同的内存块请求。 realloc
和free
都没有缩小堆以将内存返回给操作系统。 (如果需要这样做,则需要调用操作系统的本机内存分配过程,例如Windows上的VirtualAlloc
。)